From 3617f83ffcf198c7e0718359241d5fadf2837882 Mon Sep 17 00:00:00 2001 From: leekt Date: Sat, 15 Feb 2025 00:13:54 +0900 Subject: [PATCH 001/121] chore: forge init --- .github/workflows/test.yml | 43 +++++++++++++++++++++++++ .gitignore | 14 ++++++++ README.md | 66 ++++++++++++++++++++++++++++++++++++++ foundry.toml | 6 ++++ script/Counter.s.sol | 19 +++++++++++ src/Counter.sol | 14 ++++++++ test/Counter.t.sol | 24 ++++++++++++++ 7 files changed, 186 insertions(+) create mode 100644 .github/workflows/test.yml create mode 100644 .gitignore create mode 100644 README.md create mode 100644 foundry.toml create mode 100644 script/Counter.s.sol create mode 100644 src/Counter.sol create mode 100644 test/Counter.t.sol diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 00000000..34a4a527 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,43 @@ +name: CI + +on: + push: + pull_request: + workflow_dispatch: + +env: + FOUNDRY_PROFILE: ci + +jobs: + check: + strategy: + fail-fast: true + + name: Foundry project + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Install Foundry + uses: foundry-rs/foundry-toolchain@v1 + + - name: Show Forge version + run: | + forge --version + + - name: Run Forge fmt + run: | + forge fmt --check + id: fmt + + - name: Run Forge build + run: | + forge build --sizes + id: build + + - name: Run Forge tests + run: | + forge test -vvv + id: test diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..85198aaa --- /dev/null +++ b/.gitignore @@ -0,0 +1,14 @@ +# Compiler files +cache/ +out/ + +# Ignores development broadcast logs +!/broadcast +/broadcast/*/31337/ +/broadcast/**/dry-run/ + +# Docs +docs/ + +# Dotenv file +.env diff --git a/README.md b/README.md new file mode 100644 index 00000000..9265b455 --- /dev/null +++ b/README.md @@ -0,0 +1,66 @@ +## Foundry + +**Foundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust.** + +Foundry consists of: + +- **Forge**: Ethereum testing framework (like Truffle, Hardhat and DappTools). +- **Cast**: Swiss army knife for interacting with EVM smart contracts, sending transactions and getting chain data. +- **Anvil**: Local Ethereum node, akin to Ganache, Hardhat Network. +- **Chisel**: Fast, utilitarian, and verbose solidity REPL. + +## Documentation + +https://book.getfoundry.sh/ + +## Usage + +### Build + +```shell +$ forge build +``` + +### Test + +```shell +$ forge test +``` + +### Format + +```shell +$ forge fmt +``` + +### Gas Snapshots + +```shell +$ forge snapshot +``` + +### Anvil + +```shell +$ anvil +``` + +### Deploy + +```shell +$ forge script script/Counter.s.sol:CounterScript --rpc-url --private-key +``` + +### Cast + +```shell +$ cast +``` + +### Help + +```shell +$ forge --help +$ anvil --help +$ cast --help +``` diff --git a/foundry.toml b/foundry.toml new file mode 100644 index 00000000..25b918f9 --- /dev/null +++ b/foundry.toml @@ -0,0 +1,6 @@ +[profile.default] +src = "src" +out = "out" +libs = ["lib"] + +# See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options diff --git a/script/Counter.s.sol b/script/Counter.s.sol new file mode 100644 index 00000000..cdc1fe9a --- /dev/null +++ b/script/Counter.s.sol @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.13; + +import {Script, console} from "forge-std/Script.sol"; +import {Counter} from "../src/Counter.sol"; + +contract CounterScript is Script { + Counter public counter; + + function setUp() public {} + + function run() public { + vm.startBroadcast(); + + counter = new Counter(); + + vm.stopBroadcast(); + } +} diff --git a/src/Counter.sol b/src/Counter.sol new file mode 100644 index 00000000..aded7997 --- /dev/null +++ b/src/Counter.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.13; + +contract Counter { + uint256 public number; + + function setNumber(uint256 newNumber) public { + number = newNumber; + } + + function increment() public { + number++; + } +} diff --git a/test/Counter.t.sol b/test/Counter.t.sol new file mode 100644 index 00000000..54b724f7 --- /dev/null +++ b/test/Counter.t.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.13; + +import {Test, console} from "forge-std/Test.sol"; +import {Counter} from "../src/Counter.sol"; + +contract CounterTest is Test { + Counter public counter; + + function setUp() public { + counter = new Counter(); + counter.setNumber(0); + } + + function test_Increment() public { + counter.increment(); + assertEq(counter.number(), 1); + } + + function testFuzz_SetNumber(uint256 x) public { + counter.setNumber(x); + assertEq(counter.number(), x); + } +} From 460f32903d16db5fb262ca1a6b189b2b8bf7caba Mon Sep 17 00:00:00 2001 From: leekt Date: Sat, 15 Feb 2025 00:13:55 +0900 Subject: [PATCH 002/121] forge install: forge-std v1.9.6 --- .gitmodules | 3 +++ lib/forge-std | 1 + 2 files changed, 4 insertions(+) create mode 100644 .gitmodules create mode 160000 lib/forge-std diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..888d42dc --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "lib/forge-std"] + path = lib/forge-std + url = https://github.com/foundry-rs/forge-std diff --git a/lib/forge-std b/lib/forge-std new file mode 160000 index 00000000..3b20d60d --- /dev/null +++ b/lib/forge-std @@ -0,0 +1 @@ +Subproject commit 3b20d60d14b343ee4f908cb8079495c07f5e8981 From 447297491dfe0d68ad51b5b78bbb2ff0796d0eed Mon Sep 17 00:00:00 2001 From: leekt Date: Fri, 2 May 2025 01:20:39 +0900 Subject: [PATCH 003/121] removed counter --- .gitignore | 2 ++ .gitmodules | 7 ++++++ lib/account-abstraction | 1 + lib/solady | 1 + script/Counter.s.sol | 19 --------------- src/Counter.sol | 14 ----------- src/Kernel.sol | 53 +++++++++++++++++++++++++++++++++++++++++ test/Counter.t.sol | 24 ------------------- 8 files changed, 64 insertions(+), 57 deletions(-) create mode 160000 lib/account-abstraction create mode 160000 lib/solady delete mode 100644 script/Counter.s.sol delete mode 100644 src/Counter.sol create mode 100644 src/Kernel.sol delete mode 100644 test/Counter.t.sol diff --git a/.gitignore b/.gitignore index 85198aaa..58c15b97 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,5 @@ docs/ # Dotenv file .env + +**/.DS_Store diff --git a/.gitmodules b/.gitmodules index 888d42dc..c73a09c3 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,10 @@ [submodule "lib/forge-std"] path = lib/forge-std url = https://github.com/foundry-rs/forge-std +[submodule "lib/account-abstraction"] + path = lib/account-abstraction + url = https://github.com/eth-infinitism/account-abstraction + branch = develop +[submodule "lib/solady"] + path = lib/solady + url = https://github.com/vectorized/solady diff --git a/lib/account-abstraction b/lib/account-abstraction new file mode 160000 index 00000000..cc3893bc --- /dev/null +++ b/lib/account-abstraction @@ -0,0 +1 @@ +Subproject commit cc3893bcaf2272c163ce89d5eb9eadb8e6b52db7 diff --git a/lib/solady b/lib/solady new file mode 160000 index 00000000..bf973bd7 --- /dev/null +++ b/lib/solady @@ -0,0 +1 @@ +Subproject commit bf973bd715908728ea81e49100629f7f26ecf566 diff --git a/script/Counter.s.sol b/script/Counter.s.sol deleted file mode 100644 index cdc1fe9a..00000000 --- a/script/Counter.s.sol +++ /dev/null @@ -1,19 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.13; - -import {Script, console} from "forge-std/Script.sol"; -import {Counter} from "../src/Counter.sol"; - -contract CounterScript is Script { - Counter public counter; - - function setUp() public {} - - function run() public { - vm.startBroadcast(); - - counter = new Counter(); - - vm.stopBroadcast(); - } -} diff --git a/src/Counter.sol b/src/Counter.sol deleted file mode 100644 index aded7997..00000000 --- a/src/Counter.sol +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.13; - -contract Counter { - uint256 public number; - - function setNumber(uint256 newNumber) public { - number = newNumber; - } - - function increment() public { - number++; - } -} diff --git a/src/Kernel.sol b/src/Kernel.sol new file mode 100644 index 00000000..e901e1d3 --- /dev/null +++ b/src/Kernel.sol @@ -0,0 +1,53 @@ +pragma solidity ^0.8.0; + +import {IAccount} from "account-abstraction/interfaces/IAccount.sol"; +import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; +/* + Kernel V4 + - native v0.8 support + - factory update, needs to consider 7702 context + - eip712 support + - native 7702 support + - 7579 account + - erc7821 execute interface + - execute with signature + - enable mode + - permission validation method + - signature replay + - multichain replay +*/ +contract Kernel { + + modifier onlyEntryPoint { + _; + } + /// authentication + function validateUserOp( + PackedUserOperation calldata userOp, + bytes32 userOpHash, + uint256 missingAccountFunds + ) external onlyEntryPoint payable returns (uint256 validationData) { + return _verifySignature(userOpHash, userOp.signature); + } + + function isValidSignature(bytes32 hash, bytes calldata signature) external view returns(bytes4) { + } + + function _verifySignature(bytes32 _hash, bytes calldata _signature) internal returns(uint256 validationData){ + return + } + + /// execution + function executeUserOp( + PackedUserOperation calldata userOp, + bytes32 userOpHash + ) external payable onlyEntryPoint { + } + + function execute(bytes32 mode, bytes calldata executionData) external { + } +} + +struct Verifier { + address addr; +} diff --git a/test/Counter.t.sol b/test/Counter.t.sol deleted file mode 100644 index 54b724f7..00000000 --- a/test/Counter.t.sol +++ /dev/null @@ -1,24 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.13; - -import {Test, console} from "forge-std/Test.sol"; -import {Counter} from "../src/Counter.sol"; - -contract CounterTest is Test { - Counter public counter; - - function setUp() public { - counter = new Counter(); - counter.setNumber(0); - } - - function test_Increment() public { - counter.increment(); - assertEq(counter.number(), 1); - } - - function testFuzz_SetNumber(uint256 x) public { - counter.setNumber(x); - assertEq(counter.number(), x); - } -} From 335eb4fc2f0bab3c732a1fd7ae93e526dc3edcbc Mon Sep 17 00:00:00 2001 From: leekt Date: Mon, 12 May 2025 23:07:32 +0900 Subject: [PATCH 004/121] temp - install module signature --- README.md | 86 +++++------------ src/Kernel | 0 src/Kernel.sol | 147 ++++++++++++++++++++++------- src/KernelFactory.sol | 21 +++++ src/core/ModuleManager.sol | 82 ++++++++++++++++ src/core/ValidationManager.sol | 93 ++++++++++++++++++ src/interfaces/IERC7579Modules.sol | 99 +++++++++++++++++++ src/types/Constants.sol | 9 ++ src/types/Error.sol | 10 ++ src/types/Events.sol | 5 + src/types/Types.sol | 37 ++++++++ test/Kernel.t.sol | 46 +++++++++ test/utils/EntryPointLib.sol | 16 ++++ 13 files changed, 551 insertions(+), 100 deletions(-) create mode 100644 src/Kernel create mode 100644 src/KernelFactory.sol create mode 100644 src/core/ModuleManager.sol create mode 100644 src/core/ValidationManager.sol create mode 100644 src/interfaces/IERC7579Modules.sol create mode 100644 src/types/Constants.sol create mode 100644 src/types/Error.sol create mode 100644 src/types/Events.sol create mode 100644 src/types/Types.sol create mode 100644 test/Kernel.t.sol create mode 100644 test/utils/EntryPointLib.sol diff --git a/README.md b/README.md index 9265b455..fb796003 100644 --- a/README.md +++ b/README.md @@ -1,66 +1,22 @@ -## Foundry +## TODO +- Testing + - [ ] certora testing + - [ ] unit test coverage 100% + - [ ] halmos testing + +## Kernel V4 +- [ ] native v0.8 support + - [ ] factory update, needs to consider 7702 context + - [ ] eip712 userOpHash support +- [ ] native 7702 support +- [ ] 7579 account + - [ ] erc7821 execute interface + - [ ] execute with signature +- [ ] enable mode + - [ ] allow installing modules + - [ ] allow multichain replay signature +- [ ] permission validation method +- [ ] signature replay + - [ ] multichain replay +- [ ] install with signature -**Foundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust.** - -Foundry consists of: - -- **Forge**: Ethereum testing framework (like Truffle, Hardhat and DappTools). -- **Cast**: Swiss army knife for interacting with EVM smart contracts, sending transactions and getting chain data. -- **Anvil**: Local Ethereum node, akin to Ganache, Hardhat Network. -- **Chisel**: Fast, utilitarian, and verbose solidity REPL. - -## Documentation - -https://book.getfoundry.sh/ - -## Usage - -### Build - -```shell -$ forge build -``` - -### Test - -```shell -$ forge test -``` - -### Format - -```shell -$ forge fmt -``` - -### Gas Snapshots - -```shell -$ forge snapshot -``` - -### Anvil - -```shell -$ anvil -``` - -### Deploy - -```shell -$ forge script script/Counter.s.sol:CounterScript --rpc-url --private-key -``` - -### Cast - -```shell -$ cast -``` - -### Help - -```shell -$ forge --help -$ anvil --help -$ cast --help -``` diff --git a/src/Kernel b/src/Kernel new file mode 100644 index 00000000..e69de29b diff --git a/src/Kernel.sol b/src/Kernel.sol index e901e1d3..5181d830 100644 --- a/src/Kernel.sol +++ b/src/Kernel.sol @@ -1,53 +1,130 @@ pragma solidity ^0.8.0; +import {IEntryPoint} from "account-abstraction/interfaces/IEntryPoint.sol"; import {IAccount} from "account-abstraction/interfaces/IAccount.sol"; import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; -/* - Kernel V4 - - native v0.8 support - - factory update, needs to consider 7702 context - - eip712 support - - native 7702 support - - 7579 account - - erc7821 execute interface - - execute with signature - - enable mode - - permission validation method - - signature replay - - multichain replay -*/ -contract Kernel { - - modifier onlyEntryPoint { +import {IValidator} from "./interfaces/IERC7579Modules.sol"; +import "./types/Types.sol"; +import {ModuleManager, Install} from "./core/ModuleManager.sol"; +import {ValidationManager} from "./core/ValidationManager.sol"; +import {EIP712} from "solady/utils/EIP712.sol"; +import "./types/Error.sol"; +import "./types/Events.sol"; + +contract Kernel is ValidationManager, ModuleManager, EIP712 { + IEntryPoint immutable entryPoint; + + error Unauthorized(); + + modifier onlyEntryPoint() { + require(msg.sender == address(entryPoint), Unauthorized()); _; } - /// authentication - function validateUserOp( - PackedUserOperation calldata userOp, - bytes32 userOpHash, - uint256 missingAccountFunds - ) external onlyEntryPoint payable returns (uint256 validationData) { - return _verifySignature(userOpHash, userOp.signature); + + constructor(IEntryPoint _entryPoint) { + entryPoint = _entryPoint; + } + + function _domainNameAndVersion() internal pure override returns (string memory name, string memory version) { + name = "Kernel"; + version = "0.4.0"; } - function isValidSignature(bytes32 hash, bytes calldata signature) external view returns(bytes4) { + /// authentication + struct EnableModeSignature { + Install[] packages; + bytes enableSignature; + bytes userOpSignature; } - function _verifySignature(bytes32 _hash, bytes calldata _signature) internal returns(uint256 validationData){ - return + function validateUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash, uint256 missingAccountFunds) + external + payable + onlyEntryPoint + returns (uint256 validationData) + { + (ValidationId verifier, bytes32 opHash, bytes calldata userOpSignature) = _processUserOp(userOp, userOpHash); + return _verifySignature(verifier, opHash, userOpSignature); } + function _processUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash) + internal + returns (ValidationId verifier, bytes32 opHash, bytes calldata signature) + { + /* + userOp.nonce = vMode | vType | vId + */ + (ValidationMode vMode, ValidationType vType, ValidationId vId) = _parseNonce(userOp.nonce); + _checkValidation(vMode, vType, vId); + signature = userOp.signature; + if (isEnable(vMode)) { + bool enableReplayable = isEnableReplayable(vMode); + EnableModeSignature calldata sig; + assembly { + sig := signature.offset + } + signature = sig.userOpSignature; + _verifyInstallSignature(enableReplayable, sig.packages, sig.enableSignature); + } + opHash = userOpHash; + } + + function isValidSignature(bytes32 hash, bytes calldata signature) external view returns (bytes4) {} + /// execution - function executeUserOp( - PackedUserOperation calldata userOp, - bytes32 userOpHash - ) external payable onlyEntryPoint { + function executeUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash) external payable onlyEntryPoint { + (bool success, bytes memory ret) = address(this).delegatecall(userOp.callData[4:]); } - function execute(bytes32 mode, bytes calldata executionData) external { + function execute(bytes32 mode, bytes calldata executionData) external payable { + _execute(mode, executionData); } -} -struct Verifier { - address addr; + function executeFromExecutor(bytes32 mode, bytes calldata executionData) external payable { + _execute(mode, executionData); + } + + function _execute(bytes32 mode, bytes calldata executionData) internal {} + + /// management + struct InstallModuleDataFormat { + bytes installData; + bytes internalData; + } + + function installModule(uint256 moduleType, address module, bytes calldata initData) external payable { + InstallModuleDataFormat calldata imdf; + assembly { + imdf := initData.offset + } + + _installModule(moduleType, module, imdf.installData, imdf.internalData); + } + // NOTE : this ONLY allows root signature + + function installModule(bool replayable, Install[] calldata packages, bytes calldata signature) external { + require(_verifyInstallSignature(replayable, packages, signature), InstallSignatureVerificationFailed()); + _install(packages); + } + + function _verifyInstallSignature(bool replayable, Install[] calldata packages, bytes calldata signature) + internal + view + returns (bool success) + { + ValidationId vId = _validationStorage().rootValidator; + function(bytes32) internal view returns(bytes32) hashTypedData = + replayable ? _hashTypedDataSansChainId : _hashTypedData; + bytes32 digest = hashTypedData( + keccak256( + abi.encode( + keccak256( + "InstallPackages(Install[] packages)Install(uint256 moduleType,address module,bytes moduleData,bytes internalData)" + ), + _installHash(packages) + ) + ) + ); + _verifySignature(vId, digest, signature); + } } diff --git a/src/KernelFactory.sol b/src/KernelFactory.sol new file mode 100644 index 00000000..4c811dfc --- /dev/null +++ b/src/KernelFactory.sol @@ -0,0 +1,21 @@ +pragma solidity ^0.8.0; + +import {Kernel} from "./Kernel.sol"; +import {LibClone} from "solady/utils/LibClone.sol"; +import {IEntryPoint} from "account-abstraction/interfaces/IEntryPoint.sol"; + +contract KernelFactory { + Kernel public immutable template; + + constructor(IEntryPoint _entryPoint) { + template = new Kernel(_entryPoint); + } + + function deploy(bytes calldata initData) external payable returns (Kernel) { + bytes32 salt = keccak256(initData); + (bool deployed, address account) = LibClone.createDeterministicERC1967(msg.value, address(template), salt); + return Kernel(payable(account)); + } + + function deployWithSignature(bytes calldata initData, bytes calldata signature) external payable returns (Kernel) {} +} diff --git a/src/core/ModuleManager.sol b/src/core/ModuleManager.sol new file mode 100644 index 00000000..985fd409 --- /dev/null +++ b/src/core/ModuleManager.sol @@ -0,0 +1,82 @@ +pragma solidity ^0.8.0; + +import "../interfaces/IERC7579Modules.sol"; +import {ValidationManager} from "./ValidationManager.sol"; +import "../types/Error.sol"; +import "../types/Events.sol"; + +struct Install { + uint256 moduleType; + address module; + bytes moduleData; + bytes internalData; +} + +struct Uninstall { + uint256 moduleType; + address module; + bytes data; +} + +function calldataKeccak(bytes calldata data) pure returns (bytes32 ret) { + assembly ("memory-safe") { + let mem := mload(0x40) + let len := data.length + calldatacopy(mem, data.offset, len) + ret := keccak256(mem, len) + } +} + +contract ModuleManager is ValidationManager { + function _installHash(Install[] calldata packages) internal pure returns (bytes32) { + bytes32[] memory packageHashes = new bytes32[](packages.length); + for (uint256 i = 0; i < packages.length; i++) { + Install calldata pkg = packages[i]; + packageHashes[i] = keccak256( + abi.encode(pkg.moduleType, pkg.module, calldataKeccak(pkg.moduleData), calldataKeccak(pkg.internalData)) + ); + } + return keccak256(abi.encodePacked(packageHashes)); + } + + function _installModule(uint256 moduleType, address module, bytes calldata moduleData, bytes calldata internalData) + internal + { + function(address, bytes calldata, bool) hook; + if (moduleType == 1) { + hook = _installValidatorHook; + } else { + revert NotImplemented(); + } + _install(module, moduleData, internalData, hook); + emit ModuleInstalled(moduleType, module); + } + + function _install(Install[] calldata packages) internal { + for (uint256 i = 0; i < packages.length; i++) { + Install calldata pkg = packages[i]; + _installModule(pkg.moduleType, pkg.module, pkg.moduleData, pkg.internalData); + } + } + + function _install( + address module, + bytes calldata data, + bytes calldata internalData, + function(address, bytes calldata, bool) hook + ) internal { + (bool success,) = module.call(abi.encodeWithSelector(IModule.onInstall.selector, data)); + hook(module, internalData, success); + } + + function _uninstall( + address module, + bytes calldata data, + bytes calldata internalData, + function(address, bytes calldata, bool) hook + ) internal { + // TODO: make sure we use extra safe call + (bool success,) = module.call(abi.encodeWithSelector(IModule.onUninstall.selector, data)); + hook(module, internalData, success); + } +} diff --git a/src/core/ValidationManager.sol b/src/core/ValidationManager.sol new file mode 100644 index 00000000..b52ffa16 --- /dev/null +++ b/src/core/ValidationManager.sol @@ -0,0 +1,93 @@ +pragma solidity ^0.8.0; + +import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; +import "../interfaces/IERC7579Modules.sol"; +import "../types/Error.sol"; +import "../types/Types.sol"; +import "../types/Constants.sol"; + +struct ValidationInfo { + bool enabled; + bytes4 group; +} + +struct ValidationGroupInfo { + mapping(bytes4 selector => bool) allowed; + bytes32 permission; +} + +struct ValidationStorage { + ValidationId rootValidator; + mapping(IValidator validator => ValidationInfo) vInfo; + mapping(bytes4 group => ValidationGroupInfo) gInfo; +} + +function getValidator(ValidationId vId) pure returns (address v) { + assembly { + v := shr(96, vId) + } +} + +function getType(ValidationId validator) pure returns (ValidationType vType) { + assembly { + vType := validator + } +} + +contract ValidationManager { + function _validationStorage() internal view returns (ValidationStorage storage $) { + assembly { + $.slot := VALIDATION_MANAGER_STORAGE_SLOT + } + } + + function _installValidatorHook(address _validator, bytes calldata _internalData, bool _installSuccess) internal { + require(_installSuccess, ModuleInstallFailed()); + ValidationStorage storage $ = _validationStorage(); + $.vInfo[IValidator(_validator)].enabled = true; + } + + function _uninstallValidatorHook(address _validator, bytes calldata _internalData, bool _uninstallSuccess) + internal + { + require(_uninstallSuccess, ModuleUninstallFailed()); + ValidationStorage storage $ = _validationStorage(); + $.vInfo[IValidator(_validator)].enabled = false; + } + + function _checkValidation(ValidationMode vMode, ValidationType vType, ValidationId vId) internal view { + ValidationStorage storage $ = _validationStorage(); + ValidationId v; + if (vType == VALIDATION_TYPE_ROOT) { + v = $.rootValidator; + } else { + v = vId; + require($.vInfo[IValidator(getValidator(v))].enabled, InvalidValidator()); + } + // TODO : add permission support + } + + function _parseNonce(uint256 nonce) + internal + pure + returns (ValidationMode vMode, ValidationType vType, ValidationId vId) + { + // 2bytes mode (1byte currentMode, 1byte type) + // 20bytes identifier + // 1byte mode | 1byte type | 20bytes vId | 2byte nonceKey | 8byte nonce == 32bytes + assembly { + vMode := nonce + vType := shl(8, nonce) + vId := shl(16, nonce) + } + } + + function _verifySignature(ValidationId vId, bytes32 _hash, bytes calldata _signature) + internal + view + returns (uint256 validationData) + { + IValidator validator = IValidator(getValidator(vId)); // TODO: add permission support; + validator.isValidSignatureWithSender(address(0), /*NOTE: fix this */ _hash, _signature); + } +} diff --git a/src/interfaces/IERC7579Modules.sol b/src/interfaces/IERC7579Modules.sol new file mode 100644 index 00000000..e0864ba5 --- /dev/null +++ b/src/interfaces/IERC7579Modules.sol @@ -0,0 +1,99 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.21; + +import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; + +interface IModule { + error AlreadyInitialized(address smartAccount); + error NotInitialized(address smartAccount); + + /** + * @dev This function is called by the smart account during installation of the module + * @param data arbitrary data that may be required on the module during `onInstall` + * initialization + * + * MUST revert on error (i.e. if module is already enabled) + */ + function onInstall(bytes calldata data) external payable; + + /** + * @dev This function is called by the smart account during uninstallation of the module + * @param data arbitrary data that may be required on the module during `onUninstall` + * de-initialization + * + * MUST revert on error + */ + function onUninstall(bytes calldata data) external payable; + + /** + * @dev Returns boolean value if module is a certain type + * @param moduleTypeId the module type ID according the ERC-7579 spec + * + * MUST return true if the module is of the given type and false otherwise + */ + function isModuleType(uint256 moduleTypeId) external view returns (bool); + + /** + * @dev Returns if the module was already initialized for a provided smartaccount + */ + function isInitialized(address smartAccount) external view returns (bool); +} + +interface IValidator is IModule { + error InvalidTargetAddress(address target); + + /** + * @dev Validates a transaction on behalf of the account. + * This function is intended to be called by the MSA during the ERC-4337 validation phase + * Note: solely relying on bytes32 hash and signature is not sufficient for some + * validation implementations (i.e. SessionKeys often need access to userOp.calldata) + * @param userOp The user operation to be validated. The userOp MUST NOT contain any metadata. + * The MSA MUST clean up the userOp before sending it to the validator. + * @param userOpHash The hash of the user operation to be validated + * @return return value according to ERC-4337 + */ + function validateUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash) + external + payable + returns (uint256); + + /** + * Validator can be used for ERC-1271 validation + */ + function isValidSignatureWithSender(address sender, bytes32 hash, bytes calldata data) + external + view + returns (bytes4); +} + +interface IExecutor is IModule {} + +interface IHook is IModule { + function preCheck(address msgSender, uint256 msgValue, bytes calldata msgData) + external + payable + returns (bytes memory hookData); + + function postCheck(bytes calldata hookData) external payable; +} + +interface IFallback is IModule {} + +interface IPolicy is IModule { + function checkUserOpPolicy(bytes32 id, PackedUserOperation calldata userOp) external payable returns (uint256); + function checkSignaturePolicy(bytes32 id, address sender, bytes32 hash, bytes calldata sig) + external + view + returns (uint256); +} + +interface ISigner is IModule { + function checkUserOpSignature(bytes32 id, PackedUserOperation calldata userOp, bytes32 userOpHash) + external + payable + returns (uint256); + function checkSignature(bytes32 id, address sender, bytes32 hash, bytes calldata sig) + external + view + returns (bytes4); +} diff --git a/src/types/Constants.sol b/src/types/Constants.sol new file mode 100644 index 00000000..7c682aec --- /dev/null +++ b/src/types/Constants.sol @@ -0,0 +1,9 @@ +pragma solidity ^0.8.0; + +import "./Types.sol"; + +// TODO: change this -- recalculate +bytes32 constant VALIDATION_MANAGER_STORAGE_SLOT = 0x7bcaa2ced2a71450ed5a9a1b4848e8e5206dbc3f06011e595f7f55428cc6f84f; +ValidationType constant VALIDATION_TYPE_ROOT = ValidationType.wrap(0x00); +ValidationType constant VALIDATION_TYPE_VALIDATOR = ValidationType.wrap(0x01); +ValidationType constant VALIDATION_TYPE_PERMISSION = ValidationType.wrap(0x02); diff --git a/src/types/Error.sol b/src/types/Error.sol new file mode 100644 index 00000000..f11c198f --- /dev/null +++ b/src/types/Error.sol @@ -0,0 +1,10 @@ +pragma solidity ^0.8.0; + +error ModuleInstallFailed(); +error ModuleUninstallFailed(); + +error InvalidValidator(); + +error NotImplemented(); + +error InstallSignatureVerificationFailed(); diff --git a/src/types/Events.sol b/src/types/Events.sol new file mode 100644 index 00000000..10710bd6 --- /dev/null +++ b/src/types/Events.sol @@ -0,0 +1,5 @@ +pragma solidity ^0.8.0; + +event ModuleInstalled(uint256 moduleType, address module); + +event ModuleUninstalled(uint256 moduleType, address module); diff --git a/src/types/Types.sol b/src/types/Types.sol new file mode 100644 index 00000000..f56afc80 --- /dev/null +++ b/src/types/Types.sol @@ -0,0 +1,37 @@ +pragma solidity ^0.8.0; + +// --- Kernel validation modes --- +// ValidationMode = bytes1 +// ValidationMode = ________ +// _ => userOpSignature Replayable flag +// _ => enable flag +// _ => relayable enable signature flag +type ValidationMode is bytes1; + +type ValidationId is bytes20; + +type ValidationType is bytes1; + +using {vTypeEqual as ==} for ValidationType global; + +function vTypeEqual(ValidationType a, ValidationType b) pure returns (bool) { + return ValidationType.unwrap(a) == ValidationType.unwrap(b); +} + +function isEnable(ValidationMode vMode) pure returns (bool enable) { + assembly { + enable := iszero(iszero(and(vMode, 8))) + } +} + +function isReplayable(ValidationMode vMode) pure returns (bool replayable) { + assembly { + replayable := iszero(iszero(and(vMode, 64))) + } +} + +function isEnableReplayable(ValidationMode vMode) pure returns (bool replayable) { + assembly { + replayable := iszero(iszero(and(vMode, 4))) + } +} diff --git a/test/Kernel.t.sol b/test/Kernel.t.sol new file mode 100644 index 00000000..4dc9256b --- /dev/null +++ b/test/Kernel.t.sol @@ -0,0 +1,46 @@ +pragma solidity ^0.8.0; + +import {Test} from "forge-std/Test.sol"; +import {EntryPointLib} from "./utils/EntryPointLib.sol"; +import {IEntryPoint} from "account-abstraction/interfaces/IEntryPoint.sol"; +import {Kernel} from "src/Kernel.sol"; +import {KernelFactory} from "src/KernelFactory.sol"; + +contract MockValidator { + event MockInstall(bytes data); + event MockUninstall(bytes data); + + function onInstall(bytes calldata data) external payable { + emit MockInstall(data); + } + + function onUninstall(bytes calldata data) external payable { + emit MockUninstall(data); + } +} + +contract KernelTest is Test { + IEntryPoint ep; + KernelFactory factory; + MockValidator mockValidator; + Kernel kernel; + + function setUp() external { + ep = EntryPointLib.deploy(); + factory = new KernelFactory(ep); + mockValidator = new MockValidator(); + _initialize(); + } + + function _initialize() internal { + kernel = factory.deploy(abi.encode("Kernel Test")); + } + + function test_deploy() external { + Kernel k = factory.deploy(hex""); + } + + function test_install_validator() external { + kernel.installModule(1, address(mockValidator), abi.encode(hex"deadbeef", "InternalData")); + } +} diff --git a/test/utils/EntryPointLib.sol b/test/utils/EntryPointLib.sol new file mode 100644 index 00000000..f91f5fd3 --- /dev/null +++ b/test/utils/EntryPointLib.sol @@ -0,0 +1,16 @@ +pragma solidity ^0.8.0; + +import {IEntryPoint} from "account-abstraction/interfaces/IEntryPoint.sol"; + +bytes constant ENTRYPOINT_0_8_INITCODE = + hex"0a59dbff790c23c976a548690c27297883cc66b4c67024f9117b0238995e35e96101806040523461019557604051610018604082610199565b600781526020810190664552433433333760c81b82526040519161003d604084610199565b600183526020830191603160f81b8352610056816101bc565b6101205261006384610357565b61014052519020918260e05251902080610100524660a0526040519060208201927f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f8452604083015260608201524660808201523060a082015260a081526100cc60c082610199565b5190206080523060c0526040516104f58082016001600160401b0381118382101761018157829161597a833903905ff0801561017657610160526040516154ea9081610490823960805181613511015260a051816135ce015260c051816134e2015260e051816135600152610100518161358601526101205181611884015261014051816118ad0152610160518181816116ce015281816120a801528181615061015261538c0152f35b6040513d5f823e3d90fd5b634e487b7160e01b5f52604160045260245ffd5b5f80fd5b601f909101601f19168101906001600160401b0382119082101761018157604052565b908151602081105f14610236575090601f8151116101f65760208151910151602082106101e7571790565b5f198260200360031b1b161790565b604460209160405192839163305a27a960e01b83528160048401528051918291826024860152018484015e5f828201840152601f01601f19168101030190fd5b6001600160401b03811161018157600254600181811c9116801561034d575b602082101461033957601f8111610306575b50602092601f82116001146102a557928192935f9261029a575b50508160011b915f199060031b1c19161760025560ff90565b015190505f80610281565b601f1982169360025f52805f20915f5b8681106102ee57508360019596106102d6575b505050811b0160025560ff90565b01515f1960f88460031b161c191690555f80806102c8565b919260206001819286850151815501940192016102b5565b60025f52601f60205f20910160051c810190601f830160051c015b81811061032e5750610267565b5f8155600101610321565b634e487b7160e01b5f52602260045260245ffd5b90607f1690610255565b908151602081105f14610382575090601f8151116101f65760208151910151602082106101e7571790565b6001600160401b03811161018157600354600181811c91168015610485575b602082101461033957601f8111610452575b50602092601f82116001146103f157928192935f926103e6575b50508160011b915f199060031b1c19161760035560ff90565b015190505f806103cd565b601f1982169360035f52805f20915f5b86811061043a5750836001959610610422575b505050811b0160035560ff90565b01515f1960f88460031b161c191690555f8080610414565b91926020600181928685015181550194019201610401565b60035f52601f60205f20910160051c810190601f830160051c015b81811061047a57506103b3565b5f815560010161046d565b90607f16906103a156fe6101606040526004361015610024575b3615610019575f80fd5b610022336131f4565b005b5f610140525f3560e01c806242dc53146125d957806301ffc9a7146124875780630396cb60146120cc57806309ccb8801461205b5780630bd28e3b14611fbf57806313c65a6e14611f84578063154e58dc14611f295780631b2e01b814611e93578063205c287814611cf257806322cdde4c14611c6e57806335567e1a14611bb45780635287ce1214611a9457806370a0823114611a29578063765e827f1461198b57806384b0196e1461184b578063850aaf62146117865780639b249f6914611622578063b760faf9146115e1578063bb9fe6bf146113f2578063c23a5cea1461114f5763dbed18e00361000f5734610ec95761012136612d56565b6101005260e052610130613824565b6101405190815b60e0518110610f2e575061014a8261303a565b61012052610140516080526101405160c0525b60e05160c0511061029b577fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f9726101405161014051a161014051608081905290815b60e05181106101e1576101b48361010051614a19565b610140517f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005d6101405180f35b6102436101f18260e05185613267565b73ffffffffffffffffffffffffffffffffffffffff610212602083016132fb565b167f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d6101405161014051a2806132a7565b9061014051915b80831061025c5750505060010161019e565b909194600190610289610270888587613109565b61027f60805161012051613176565b519060805161437c565b0195816080510160805201919061024a565b6102aa60c05160e05183613267565b73ffffffffffffffffffffffffffffffffffffffff6102d860206102ce84806132a7565b60a05293016132fb565b61014051911691905b60a05181106103055750505060a05160805101608052600160c0510160c05261015d565b610316816080510161012051613176565b516103248260a05185613109565b61014051915a81519273ffffffffffffffffffffffffffffffffffffffff61034b826132fb565b168452602081810135908501526fffffffffffffffffffffffffffffffff6080808301358281166060880152811c604087015260a083013560c0808801919091528301359182166101008701521c6101208501526103ac60e082018261331c565b9081610e15575b5050604051936103c282612ee9565b6020850152846040526040810151946effffffffffffffffffffffffffffff8660c08401511760608401511760808401511760a084015117610100840151176101208401511711610daf5750604081015160608201510160808201510160a08201510160c0820151016101008201510294856040860152845173ffffffffffffffffffffffffffffffffffffffff60e08183511692610475898d61046960408b018b61331c565b92909160805101614fb5565b0151169661014051978015610d7e575b87516040810151905173ffffffffffffffffffffffffffffffffffffffff169061014051506040519a8b8960208d01519260208301937f19822f7c00000000000000000000000000000000000000000000000000000000855260248401926104ec93615460565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081018d5261051c908d612c2d565b61014051908c5190846101405190602095f161014051519a3d602003610d73575b60405215610c80575015610c02575b505073ffffffffffffffffffffffffffffffffffffffff825116602083015190610140515260016020526040610140512077ffffffffffffffffffffffffffffffffffffffffffffffff8260401c165f5260205267ffffffffffffffff60405f20918254926105ba84612e80565b90551603610b99575a840311610b305760e0015160609073ffffffffffffffffffffffffffffffffffffffff16610827575b73ffffffffffffffffffffffffffffffffffffffff949260a0859360809360606106219801520135905a900301910152614f15565b911685036107be576107555761064b73ffffffffffffffffffffffffffffffffffffffff91614f15565b91166106ec5761065d576001016102e1565b60a490604051907f220266b600000000000000000000000000000000000000000000000000000000825260805101600482015260406024820152602160448201527f41413332207061796d61737465722065787069726564206f72206e6f7420647560648201527f65000000000000000000000000000000000000000000000000000000000000006084820152fd5b608482604051907f220266b600000000000000000000000000000000000000000000000000000000825260805101600482015260406024820152601460448201527f41413334207369676e6174757265206572726f720000000000000000000000006064820152fd5b608482604051907f220266b600000000000000000000000000000000000000000000000000000000825260805101600482015260406024820152601760448201527f414132322065787069726564206f72206e6f74206475650000000000000000006064820152fd5b608483604051907f220266b600000000000000000000000000000000000000000000000000000000825260805101600482015260406024820152601460448201527f41413234207369676e6174757265206572726f720000000000000000000000006064820152fd5b9897969594505a9883519961085b73ffffffffffffffffffffffffffffffffffffffff60e08d015116604087015190615482565b15610ac75760807f52b7512c000000000000000000000000000000000000000000000000000000009798999a9b01516040516108dc816108b060208a015160408b015190602084019d8e528960248501615460565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282612c2d565b8651608073ffffffffffffffffffffffffffffffffffffffff60e08301511691015161014051918b61014051928551926101405191f1983d908161014051843e51948251604084019b8c519015918215610abb575b508115610a8b575b50610a065750601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09101160191826040525a90031161097a5750946105ec565b80887f220266b60000000000000000000000000000000000000000000000000000000060a4935260805101600482015260406024820152602760448201527f41413336206f766572207061796d6173746572566572696669636174696f6e4760648201527f61734c696d6974000000000000000000000000000000000000000000000000006084820152fd5b8b610a87610a1261349e565b6040519384937f65c8fd4d0000000000000000000000000000000000000000000000000000000085526080510160048501526024840152600d60648401527f4141333320726576657274656400000000000000000000000000000000000000608484015260a0604484015260a4830190612de9565b0390fd5b9050601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa084019101105f610939565b6040141591505f610931565b608487604051907f220266b600000000000000000000000000000000000000000000000000000000825260805101600482015260406024820152601e60448201527f41413331207061796d6173746572206465706f73697420746f6f206c6f7700006064820152fd5b608487604051907f220266b600000000000000000000000000000000000000000000000000000000825260805101600482015260406024820152601e60448201527f41413236206f76657220766572696669636174696f6e4761734c696d697400006064820152fd5b608488604051907f220266b600000000000000000000000000000000000000000000000000000000825260805101600482015260406024820152601a60448201527f4141323520696e76616c6964206163636f756e74206e6f6e63650000000000006064820152fd5b610c0b91615482565b15610c17578b8061054c565b608488604051907f220266b600000000000000000000000000000000000000000000000000000000825260805101600482015260406024820152601760448201527f41413231206469646e2774207061792070726566756e640000000000000000006064820152fd5b8b903b610cf057608490604051907f220266b600000000000000000000000000000000000000000000000000000000825260805101600482015260406024820152601960448201527f41413230206163636f756e74206e6f74206465706c6f796564000000000000006064820152fd5b610cf861349e565b90610a876040519283927f65c8fd4d00000000000000000000000000000000000000000000000000000000845260805101600484015260606024840152600d60648401527f4141323320726576657274656400000000000000000000000000000000000000608484015260a0604484015260a4830190612de9565b61014051915061053d565b6101408051849052516020819052604090205490985081811115610da85750610140515b97610485565b8103610da2565b80887f220266b6000000000000000000000000000000000000000000000000000000006084935260805101600482015260406024820152601860448201527f41413934206761732076616c756573206f766572666c6f7700000000000000006064820152fd5b60348210610ed05781601411610ec95780359160248110610ec957603411610ec9576024810135608090811c60a0880152601490910135811c90860152606081901c15610e6b5760601c60e085015289806103b3565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4141393820696e76616c6964207061796d6173746572000000000000000000006044820152fd5b6101405180fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4141393320696e76616c6964207061796d6173746572416e64446174610000006044820152fd5b610f3b8160e05184613267565b92610f4684806132a7565b919073ffffffffffffffffffffffffffffffffffffffff610f69602088016132fb565b16956001871461111d5786610f86575b5050019250600101610137565b806040610f9492019061331c565b91873b15610ec957916040519283917f2dd8113300000000000000000000000000000000000000000000000000000000835286604484016040600486015252606483019160648860051b8501019281610140517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee182360301915b8b82106110c357505050505081611054917ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8580950301602485015261014051956131b6565b0381610140518a5af190816110a8575b5061109b57847f86a9f750000000000000000000000000000000000000000000000000000000006101405152600452602461014051fd5b929350839260015f610f79565b610140516110b591612c2d565b61014051610ec9575f611064565b9193967fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9c90879294969703018552863584811215610ec957602061110c600193858394016133bd565b98019501920188969594939161100e565b867f86a9f750000000000000000000000000000000000000000000000000000000006101405152600452602461014051fd5b34610ec95760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec957611186612cde565b3361014051526101405160205260016040610140512001908154916dffffffffffffffffffffffffffff8360081c169283156113945760981c65ffffffffffff1680156113365742106112d85780547fffffffffffffff000000000000000000000000000000000000000000000000ff1690556040805173ffffffffffffffffffffffffffffffffffffffff831681526020810184905233917fb7c918e0e249f999e965cafeb6c664271b3f4317d296461500e71da39f0cbda391a2610140519182918291829173ffffffffffffffffffffffffffffffffffffffff165af161126d612eba565b501561127a576101405180f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f6661696c656420746f207769746864726177207374616b6500000000000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f5374616b65207769746864726177616c206973206e6f742064756500000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f6d7573742063616c6c20756e6c6f636b5374616b6528292066697273740000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f207374616b6520746f2077697468647261770000000000000000000000006044820152fd5b34610ec957610140517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec9573361014051526101405160205260016040610140512001805463ffffffff8160781c169081156115835760ff16156115255765ffffffffffff4216019065ffffffffffff82116114f25780547fffffffffffffff000000000000ffffffffffffffffffffffffffffffffffff001678ffffffffffff00000000000000000000000000000000000000609884901b1617905560405165ffffffffffff909116815233907ffa9b3c14cc825c412c9ed81b3ba365a5b459439403f18829e572ed53a4180f0a90602090a26101405180f35b7f4e487b710000000000000000000000000000000000000000000000000000000061014051526011600452602461014051fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f616c726561647920756e7374616b696e670000000000000000000000000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f6e6f74207374616b6564000000000000000000000000000000000000000000006044820152fd5b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec95761161b611616612cde565b6131f4565b6101405180f35b34610ec95760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec95760043567ffffffffffffffff8111610ec95760206116766116b1923690600401612d01565b60405193849283927f570e1a3600000000000000000000000000000000000000000000000000000000845285600485015260248401916131b6565b03816101405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165af180156117785773ffffffffffffffffffffffffffffffffffffffff916101405191611749575b507f6ca7b80600000000000000000000000000000000000000000000000000000000610140515216600452602461014051fd5b61176b915060203d602011611771575b6117638183612c2d565b81019061318a565b82611716565b503d611759565b6040513d61014051823e3d90fd5b34610ec95760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec9576117bd612cde565b60243567ffffffffffffffff8111610ec9576117dd903690600401612d01565b604051929181908437820190610140518252610140519280610140519303915af4611806612eba565b90610a876040519283927f9941055400000000000000000000000000000000000000000000000000000000845215156004840152604060248401526044830190612de9565b34610ec957610140517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec9576119296118a87f0000000000000000000000000000000000000000000000000000000000000000614ccf565b6118d17f0000000000000000000000000000000000000000000000000000000000000000614e45565b60405190602090611937906118e68385612c2d565b6101405184525f3681376040519586957f0f00000000000000000000000000000000000000000000000000000000000000875260e08588015260e0870190612de9565b908582036040870152612de9565b4660608501523060808501526101405160a085015283810360c0850152818084519283815201930191610140515b82811061197457505050500390f35b835185528695509381019392810192600101611965565b34610ec95761199936612d56565b6119a4929192613824565b6119ad8361303a565b6119b8818585613898565b5061014051927fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f9728480a161014051915b8583106119f9576101b48585614a19565b909193600190611a1f611a0d878987613109565b611a178886613176565b51908861437c565b01940191906119e8565b34610ec95760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec95773ffffffffffffffffffffffffffffffffffffffff611a75612cde565b1661014051526101405160205260206040610140512054604051908152f35b34610ec95760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec95773ffffffffffffffffffffffffffffffffffffffff611ae0612cde565b604051611aec81612bab565b6101405181526101405160208201526101405160408201526101405160608201526080610140519101521661014051526101405160205260a06040610140512065ffffffffffff604051611b3f81612bab565b63ffffffff60018454948584520154916dffffffffffffffffffffffffffff6020820160ff8516151581526040830190828660081c1682528660806060860195878960781c168752019660981c1686526040519788525115156020880152511660408601525116606084015251166080820152f35b34610ec95760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec9576020611bed612cde565b73ffffffffffffffffffffffffffffffffffffffff611c0a612d2f565b91166101405152600182526040610140512077ffffffffffffffffffffffffffffffffffffffffffffffff82165f52825260405f20547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000006040519260401b16178152f35b34610ec95760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec95760043567ffffffffffffffff8111610ec9576101207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8236030112610ec957611cea602091600401612ee9565b604051908152f35b34610ec95760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec957611d29612cde565b6024359033610140515261014051602052604061014051208054808411611e355783611d5491612ead565b90556040805173ffffffffffffffffffffffffffffffffffffffff831681526020810184905233917fd1c19fbcd4551a5edfb66d43d2e337c04837afda3482b42bdf569a8fccdae5fb91a2610140519182918291829173ffffffffffffffffffffffffffffffffffffffff165af1611dca612eba565b5015611dd7576101405180f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6661696c656420746f20776974686472617700000000000000000000000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f576974686472617720616d6f756e7420746f6f206c61726765000000000000006044820152fd5b34610ec95760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec957611eca612cde565b73ffffffffffffffffffffffffffffffffffffffff611ee7612d2f565b91166101405152600160205277ffffffffffffffffffffffffffffffffffffffffffffffff6040610140512091165f52602052602060405f2054604051908152f35b34610ec957610140517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec95760206040517f29a0bca4af4be3421398da00295e58e6d7de38cb492214754cb6a47507dd6f8e8152f35b34610ec957610140517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec9576020611cea6134cb565b34610ec95760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec95760043577ffffffffffffffffffffffffffffffffffffffffffffffff81168103610ec957336101405152600160205277ffffffffffffffffffffffffffffffffffffffffffffffff6040610140512091165f5260205260405f206120528154612e80565b90556101405180f35b34610ec957610140517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec957602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec95760043563ffffffff8116809103610ec957336101405152610140516020526040610140512090801561242957600182015463ffffffff8160781c1682106123cb57612155906dffffffffffffffffffffffffffff349160081c16612e46565b91821561236d576dffffffffffffffffffffffffffff831161230f57546040516122d79161218282612bab565b815265ffffffffffff602082019160018352604081016dffffffffffffffffffffffffffff87168152606082019086825260016080840193610140518552336101405152610140516020526040610140512090518155019451151560ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008754169116178555517fffffffffffffffffffffffffffffffffff0000000000000000000000000000ff6effffffffffffffffffffffffffff008087549360081b16169116178455517fffffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffff72ffffffff0000000000000000000000000000008086549360781b1616911617835551167fffffffffffffff000000000000ffffffffffffffffffffffffffffffffffffff78ffffffffffff0000000000000000000000000000000000000083549260981b169116179055565b60405191825260208201527fa5ae833d0bb1dcd632d98a8b70973e8516812898e19bf27b70071ebc8dc52c0160403392a26101405180f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f7374616b65206f766572666c6f770000000000000000000000000000000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6e6f207374616b652073706563696669656400000000000000000000000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f63616e6e6f7420646563726561736520756e7374616b652074696d65000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f6d757374207370656369667920756e7374616b652064656c61790000000000006044820152fd5b34610ec95760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec9576004357fffffffff000000000000000000000000000000000000000000000000000000008116809103610ec957807f6930d3ee00000000000000000000000000000000000000000000000000000000602092149081156125af575b8115612585575b811561255b575b8115612531575b506040519015158152f35b7f01ffc9a70000000000000000000000000000000000000000000000000000000091501482612526565b7f3e84f021000000000000000000000000000000000000000000000000000000008114915061251f565b7fcf28ef970000000000000000000000000000000000000000000000000000000081149150612518565b7f989ccc580000000000000000000000000000000000000000000000000000000081149150612511565b34612a32576102007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112612a325760043567ffffffffffffffff8111612a325736602382011215612a325761263a903690602481600401359101612ca8565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc36016101c08112612a32576101406040519161267683612bab565b12612a325760405161268781612bf4565b60243573ffffffffffffffffffffffffffffffffffffffff81168103612a3257815260443560208201526064356040820152608435606082015260a435608082015260c43560a082015260e43560c08201526101043573ffffffffffffffffffffffffffffffffffffffff81168103612a325760e082015261012435610100820152610144356101208201528152602081019161016435835260408201906101843582526101a435606084015260808301916101c43583526101e43567ffffffffffffffff8111612a3257612760903690600401612d01565b955a90303303612b4d578651606081015195603f5a0260061c61271060a084015189010111612b25575f9681519182612a6b575b5050505050906127ac915a9003855101963691612ca8565b925a93855161010081015161012082015148018082105f14612a635750975b6127f873ffffffffffffffffffffffffffffffffffffffff60e08401511694518203606084015190614b09565b01925f928161290e5750505173ffffffffffffffffffffffffffffffffffffffff16945b5a900301019485029051928184105f146128ba5750506003811015612887576002036128595760209281611cea929361285481614c2a565b614b28565b7fdeadaa51000000000000000000000000000000000000000000000000000000006101405152602061014051fd5b7f4e487b710000000000000000000000000000000000000000000000000000000061014051526021600452602461014051fd5b816128f0929594969396039073ffffffffffffffffffffffffffffffffffffffff165f525f60205260405f209081540180915590565b5060038410156128875782612909926020951590614ba9565b611cea565b909691878251612921575b50505061281c565b90919293505a926003881015612a365760028803612957575b505060a061294e925a900391015190614b09565b90888080612919565b60a083015191803b15612a32578b925f92836129b3938c8b88604051998a98899788957f7c627b210000000000000000000000000000000000000000000000000000000087526004870152608060248701526084860190612de9565b9202604484015260648301520393f19081612a1d575b50612a1357610a876129d961349e565b6040519182917fad7954bc000000000000000000000000000000000000000000000000000000008352602060048401526024830190612de9565b60a061294e61293a565b5f612a2791612c2d565b5f610140528a6129c9565b5f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b9050976127cb565b915f9291838093602073ffffffffffffffffffffffffffffffffffffffff885116910192f115612a9e575b808080612794565b6127ac9392955060405191612ab161349e565b908151612aca575b505050604052600193909188612a96565b7f1c4fada7374c0a9ee8841fc38afe82932dc0f8e69012e927f061a8bae611a201905191602073ffffffffffffffffffffffffffffffffffffffff855116940151612b1a60405192839283612e2c565b0390a3888080612ab9565b7fdeaddead000000000000000000000000000000000000000000000000000000005f5260205ffd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4141393220696e7465726e616c2063616c6c206f6e6c790000000000000000006044820152fd5b60a0810190811067ffffffffffffffff821117612bc757604052565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b610140810190811067ffffffffffffffff821117612bc757604052565b6060810190811067ffffffffffffffff821117612bc757604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117612bc757604052565b67ffffffffffffffff8111612bc757601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b929192612cb482612c6e565b91612cc26040519384612c2d565b829481845281830111612a32578281602093845f960137010152565b6004359073ffffffffffffffffffffffffffffffffffffffff82168203612a3257565b9181601f84011215612a325782359167ffffffffffffffff8311612a325760208381860195010111612a3257565b6024359077ffffffffffffffffffffffffffffffffffffffffffffffff82168203612a3257565b9060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc830112612a325760043567ffffffffffffffff8111612a325760040182601f82011215612a325780359267ffffffffffffffff8411612a32576020808301928560051b010111612a3257919060243573ffffffffffffffffffffffffffffffffffffffff81168103612a325790565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f602080948051918291828752018686015e5f8582860101520116010190565b604090612e43939281528160208201520190612de9565b90565b91908201809211612e5357565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114612e535760010190565b91908203918211612e5357565b3d15612ee4573d90612ecb82612c6e565b91612ed96040519384612c2d565b82523d5f602084013e565b606090565b604290612ef5816135f4565b612efd6134cb565b91612f07816132fb565b91801561300557905b60c0612f1f606083018361331c565b90816040519182372091612f3660e082018261331c565b908160405191823720926040519473ffffffffffffffffffffffffffffffffffffffff60208701977f29a0bca4af4be3421398da00295e58e6d7de38cb492214754cb6a47507dd6f8e895216604087015260208301356060870152608086015260a085015260808101358285015260a081013560e085015201356101008301526101208201526101208152612fcd61014082612c2d565b519020604051917f19010000000000000000000000000000000000000000000000000000000000008352600283015260228201522090565b50613013604082018261331c565b90816040519182372090612f10565b67ffffffffffffffff8111612bc75760051b60200190565b9061304482613022565b6130516040519182612c2d565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe061307f8294613022565b01905f5b82811061308f57505050565b60209060405161309e81612bab565b6040516130aa81612bf4565b5f81525f848201525f60408201525f60608201525f60808201525f60a08201525f60c08201525f60e08201525f6101008201525f61012082015281525f838201525f60408201525f60608201525f608082015282828501015201613083565b91908110156131495760051b810135907ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee181360301821215612a32570190565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b80518210156131495760209160051b010190565b90816020910312612a32575173ffffffffffffffffffffffffffffffffffffffff81168103612a325790565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe093818652868601375f8582860101520116010190565b7f2da466a7b24304f47e87fa2e1e5a81b9831ce54fec19055ce277ca2f39ba42c4602073ffffffffffffffffffffffffffffffffffffffff61325b348573ffffffffffffffffffffffffffffffffffffffff165f525f60205260405f209081540180915590565b936040519485521692a2565b91908110156131495760051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa181360301821215612a32570190565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215612a32570180359067ffffffffffffffff8211612a3257602001918160051b36038313612a3257565b3573ffffffffffffffffffffffffffffffffffffffff81168103612a325790565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215612a32570180359067ffffffffffffffff8211612a3257602001918136038313612a3257565b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe182360301811215612a3257016020813591019167ffffffffffffffff8211612a32578136038313612a3257565b80359173ffffffffffffffffffffffffffffffffffffffff83168303612a325773ffffffffffffffffffffffffffffffffffffffff612e43931681526020820135602082015261348f61348361344a61342f61341c604087018761336d565b61012060408801526101208701916131b6565b61343c606087018761336d565b9086830360608801526131b6565b6080850135608085015260a085013560a085015260c085013560c085015261347560e086018661336d565b9085830360e08701526131b6565b9261010081019061336d565b916101008185039101526131b6565b3d61080081116134c2575b604051906020818301016040528082525f602083013e90565b506108006134a9565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163014806135cb575b15613533577f000000000000000000000000000000000000000000000000000000000000000090565b60405160208101907f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f82527f000000000000000000000000000000000000000000000000000000000000000060408201527f000000000000000000000000000000000000000000000000000000000000000060608201524660808201523060a082015260a081526135c560c082612c2d565b51902090565b507f0000000000000000000000000000000000000000000000000000000000000000461461350a565b613601604082018261331c565b909161360d8284614c7a565b1561381d5761361b906132fb565b60175f80833c5f51907fef010000000000000000000000000000000000000000000000000000000000007fffffff000000000000000000000000000000000000000000000000000000000083160361375b575060181b91601482116136bb5750506040517fffffffffffffffffffffffffffffffffffffffff000000000000000000000000808060208401941616168252601481526135c5603482612c2d565b81601411612a325760206135c5916040519384917fffffffffffffffffffffffffffffffffffffffff000000000000000000000000808086860199161616875260147fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec83019101603484013781015f8382015203017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282612c2d565b3b156137bf5760646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f6e6f7420616e204549502d373730322064656c656761746500000000000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f73656e64657220686173206e6f20636f646500000000000000000000000000006044820152fd5b5050505f90565b7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005c6138705760017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005d565b7f3ee5aeb5000000000000000000000000000000000000000000000000000000005f5260045ffd5b92919092835f5b8181106138ac5750505050565b6138b68185613176565b516138c2828486613109565b5f915a81519273ffffffffffffffffffffffffffffffffffffffff6138e6826132fb565b168452602081013560208501526080810135936fffffffffffffffffffffffffffffffff8560801c951694604082019060608301968752815260c0820160a0840135815260c0840135906fffffffffffffffffffffffffffffffff8260801c9216916101208501906101008601938452815261396560e087018761331c565b9081614316575b505060405161397a87612ee9565b9960208a019a8b528160405285519586855117825117926effffffffffffffffffffffffffffff60808a01948551179560a08b0196875117895117905117116142b45750519051019051019051019051019051029560408601918783528973ffffffffffffffffffffffffffffffffffffffff60e08951613a0f8b8483511695613a0760408d018d61331c565b929091614fb5565b015116985f99801561428d575b89516040810151905173ffffffffffffffffffffffffffffffffffffffff1680916040519d8e808d8b519360208301947f19822f7c0000000000000000000000000000000000000000000000000000000086526024840192613a7d93615460565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081018252613aad9082612c2d565b51905f6020948194f15f519c3d602003614285575b6040521561419a575015614120575b505073ffffffffffffffffffffffffffffffffffffffff8451166020850151905f52600160205260405f2077ffffffffffffffffffffffffffffffffffffffffffffffff8260401c165f5260205267ffffffffffffffff60405f2091825492613b3984612e80565b905516036140bb575a8603116140565773ffffffffffffffffffffffffffffffffffffffff60e0606094015116613d96575b505073ffffffffffffffffffffffffffffffffffffffff949260a085936080936060613ba29801520135905a900301910152614f15565b9116613d3157613ccc57613bca73ffffffffffffffffffffffffffffffffffffffff91614f15565b9116613c6757613bdc5760010161389f565b60a490604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152602160448201527f41413332207061796d61737465722065787069726564206f72206e6f7420647560648201527f65000000000000000000000000000000000000000000000000000000000000006084820152fd5b608482604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601460448201527f41413334207369676e6174757265206572726f720000000000000000000000006064820152fd5b608482604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601760448201527f414132322065787069726564206f72206e6f74206475650000000000000000006064820152fd5b608483604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601460448201527f41413234207369676e6174757265206572726f720000000000000000000000006064820152fd5b909c9b9a99989796505a9085519d60e08f015173ffffffffffffffffffffffffffffffffffffffff168151613dca91615482565b15613ff157613e1d7f52b7512c00000000000000000000000000000000000000000000000000000000999a9b9c9d9e9f60800151926108b060405193849251905190602084019d8e528960248501615460565b5f8088518b82608073ffffffffffffffffffffffffffffffffffffffff60e08501511693015192865193f1983d90815f843e51948251604084019b8c519015918215613fe5575b508115613fb5575b50613f385750601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09101160191826040525a900311613eb05750948260a0613b6b565b80887f220266b60000000000000000000000000000000000000000000000000000000060a49352600482015260406024820152602760448201527f41413336206f766572207061796d6173746572566572696669636174696f6e4760648201527f61734c696d6974000000000000000000000000000000000000000000000000006084820152fd5b8b610a87613f4461349e565b6040519384937f65c8fd4d00000000000000000000000000000000000000000000000000000000855260048501526024840152600d60648401527f4141333320726576657274656400000000000000000000000000000000000000608484015260a0604484015260a4830190612de9565b9050601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa084019101105f613e6c565b6040141591505f613e64565b608489604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601e60448201527f41413331207061796d6173746572206465706f73697420746f6f206c6f7700006064820152fd5b608489604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601e60448201527f41413236206f76657220766572696669636174696f6e4761734c696d697400006064820152fd5b60848a604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601a60448201527f4141323520696e76616c6964206163636f756e74206e6f6e63650000000000006064820152fd5b61412991615482565b15614135575f80613ad1565b60848a604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601760448201527f41413231206469646e2774207061792070726566756e640000000000000000006064820152fd5b8d903b61420657608490604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601960448201527f41413230206163636f756e74206e6f74206465706c6f796564000000000000006064820152fd5b61420e61349e565b90610a876040519283927f65c8fd4d000000000000000000000000000000000000000000000000000000008452600484015260606024840152600d60648401527f4141323320726576657274656400000000000000000000000000000000000000608484015260a0604484015260a4830190612de9565b5f9150613ac2565b9950815f525f60205260405f20548181115f146142ad57505f5b99613a1c565b81036142a7565b808f7f220266b60000000000000000000000000000000000000000000000000000000060849352600482015260406024820152601860448201527f41413934206761732076616c756573206f766572666c6f7700000000000000006064820152fd5b60348210610ed05781601411612a3257803560601c9160248110612a3257601482013590603411612a32576fffffffffffffffffffffffffffffffff60248193013560801c1660a089015260801c1660808701528015610e6b5760e08601525f8061396c565b9092915a60608201516040519586614397606083018361331c565b5f60038211614a11575b7fffffffff00000000000000000000000000000000000000000000000000000000167f8dd7712f00000000000000000000000000000000000000000000000000000000036148a3575050505f6144ae6145a261443c61446e602095868a01516040519384927f8dd7712f000000000000000000000000000000000000000000000000000000008a8501526040602485015260648401906133bd565b906044830152037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282612c2d565b6108b06040519384927e42dc5300000000000000000000000000000000000000000000000000000000888501526102006024850152610224840190612de9565b614571604484018b60806101a091610120815173ffffffffffffffffffffffffffffffffffffffff8151168652602081015160208701526040810151604087015260608101516060870152838101518487015260a081015160a087015260c081015160c087015273ffffffffffffffffffffffffffffffffffffffff60e08201511660e087015261010081015161010087015201516101208501526020810151610140850152604081015161016085015260608101516101808501520151910152565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc8382030161020484015287612de9565b828151910182305af15f5196604052156145bd575b50505050565b9091929394505f3d602014614896575b7fdeaddead00000000000000000000000000000000000000000000000000000000810361465957608485604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152600f60448201527f41413935206f7574206f662067617300000000000000000000000000000000006064820152fd5b92935090917fdeadaa5100000000000000000000000000000000000000000000000000000000036146bc57506146a16146966146b1925a90612ead565b608084015190612e46565b6040830151836128548295614c2a565b905b5f8080806145b7565b9061472f9060405160208501518551907ff62676f440ff169a3a9afdbf812e89e7f95975ee8e5c31214ffdef631c5f4792602073ffffffffffffffffffffffffffffffffffffffff84511693015161471261349e565b9061472260405192839283612e2c565b0390a36040525a90612ead565b61473f6080840191825190612e46565b915f905a92855161010081015161012082015148018082105f1461488e5750955b61478d73ffffffffffffffffffffffffffffffffffffffff60e08401511693518203606084015190614b09565b01925f928061485f5750505173ffffffffffffffffffffffffffffffffffffffff16935b5a900301019283026040850151928184105f14614813575050806147e6575090816147e0929361285481614c2a565b906146b3565b807f4e487b7100000000000000000000000000000000000000000000000000000000602492526021600452fd5b614848908284939795039073ffffffffffffffffffffffffffffffffffffffff165f525f60205260405f209081540180915590565b506147e6575090825f61485a93614ba9565b6147e0565b9591905161486e575b506147b1565b935090506148875a9360a05f955a900391015190614b09565b905f614868565b905095614760565b5060205f803e5f516145cd565b614a0893506149dc916148e8917e42dc5300000000000000000000000000000000000000000000000000000000602086015261020060248601526102248501916131b6565b6149ab604484018860806101a091610120815173ffffffffffffffffffffffffffffffffffffffff8151168652602081015160208701526040810151604087015260608101516060870152838101518487015260a081015160a087015260c081015160c087015273ffffffffffffffffffffffffffffffffffffffff60e08201511660e087015261010081015161010087015201516101208501526020810151610140850152604081015161016085015260608101516101808501520151910152565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc8382030161020484015284612de9565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101885287612c2d565b60205f876145a2565b5081356143a1565b73ffffffffffffffffffffffffffffffffffffffff168015614aab575f80809381935af1614a45612eba565b5015614a4d57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f41413931206661696c65642073656e6420746f2062656e6566696369617279006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4141393020696e76616c69642062656e656669636961727900000000000000006044820152fd5b90619c408201811115614b2257606491600a9103020490565b50505f90565b9190917f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f6080602083015192519473ffffffffffffffffffffffffffffffffffffffff86511694602073ffffffffffffffffffffffffffffffffffffffff60e089015116970151916040519283525f602084015260408301526060820152a4565b9060807f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f91602084015193519573ffffffffffffffffffffffffffffffffffffffff87511695602073ffffffffffffffffffffffffffffffffffffffff60e08a015116980151926040519384521515602084015260408301526060820152a4565b60208101519051907f67b4fa9642f42120bf031f3051d1824b0fe25627945b27b8a6a65d5761d5482e60208073ffffffffffffffffffffffffffffffffffffffff855116940151604051908152a3565b90600211614cca57357fffffffffffffffffffffffffffffffffffffffff000000000000000000000000167f77020000000000000000000000000000000000000000000000000000000000001490565b505f90565b60ff8114614d2e5760ff811690601f8211614d065760405191614cf3604084612c2d565b6020808452838101919036833783525290565b7fb3512b0c000000000000000000000000000000000000000000000000000000005f5260045ffd5b506040515f6002548060011c9160018216918215614e3b575b602084108314614e0e578385528492908115614dd15750600114614d72575b612e4392500382612c2d565b5060025f90815290917f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace5b818310614db5575050906020612e4392820101614d66565b6020919350806001915483858801015201910190918392614d9d565b60209250612e439491507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001682840152151560051b820101614d66565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b92607f1692614d47565b60ff8114614e695760ff811690601f8211614d065760405191614cf3604084612c2d565b506040515f6003548060011c9160018216918215614f0b575b602084108314614e0e578385528492908115614dd15750600114614eac57612e4392500382612c2d565b5060035f90815290917fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b5b818310614eef575050906020612e4392820101614d66565b6020919350806001915483858801015201910190918392614ed7565b92607f1692614e82565b8015614fae575f60408051614f2981612c11565b828152826020820152015273ffffffffffffffffffffffffffffffffffffffff81169065ffffffffffff8160a01c16908115614fa0575b60409060d01c9165ffffffffffff825191614f7a83612c11565b8583528460208401521691829101524211908115614f9757509091565b90504211159091565b65ffffffffffff9150614f60565b505f905f90565b929190915f9080614fc8575b5050505050565b83519473ffffffffffffffffffffffffffffffffffffffff86511695614fee8386614c7a565b61535f5750853b6152fa576014821061529557604085510151602060405180927f570e1a36000000000000000000000000000000000000000000000000000000008252826004830152818781615048602482018a8d6131b6565b039273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690f190811561528a57849161526b575b5073ffffffffffffffffffffffffffffffffffffffff811680156152065787036151a1573b1561513c5750601411615139577fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d91604091503573ffffffffffffffffffffffffffffffffffffffff60e06020860151955101511673ffffffffffffffffffffffffffffffffffffffff83519260601c1682526020820152a35f80808080614fc1565b80fd5b608490604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152602060448201527f4141313520696e6974436f6465206d757374206372656174652073656e6465726064820152fd5b608482604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152602060448201527f4141313420696e6974436f6465206d7573742072657475726e2073656e6465726064820152fd5b608483604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601b60448201527f4141313320696e6974436f6465206661696c6564206f72204f4f4700000000006064820152fd5b615284915060203d602011611771576117638183612c2d565b5f615091565b6040513d86823e3d90fd5b608490604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601760448201527f4141393920696e6974436f646520746f6f20736d616c6c0000000000000000006064820152fd5b608490604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601f60448201527f414131302073656e64657220616c726561647920636f6e7374727563746564006064820152fd5b945050919050601482116153735750505050565b604073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169301519082601411612a3257833b15612a32575f809461542f96604051978896879586937fc09ad0d900000000000000000000000000000000000000000000000000000000855260048501526040602485015260147fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec60448601930191016131b6565b0393f1801561545557615445575b8080806145b7565b5f61544f91612c2d565b5f61543d565b6040513d5f823e3d90fd5b615478604092959493956060835260608301906133bd565b9460208201520152565b73ffffffffffffffffffffffffffffffffffffffff165f525f60205260405f2090815481811061381d5703905560019056fea2646970667358221220a2ee7c02d47f72772240d0dfa7174d99b6049a68ccdf3d4434c3918f6bd9c1e164736f6c634300081c003360a08060405234602f57336080526104c19081610034823960805181818160d80152818161023401526102e10152f35b5f80fdfe60806040526004361015610011575f80fd5b5f3560e01c8063570e1a3614610258578063b0d691fe146101ea5763c09ad0d91461003a575f80fd5b346101e65760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101e65760043573ffffffffffffffffffffffffffffffffffffffff811681036101e65760243567ffffffffffffffff81116101e657366023820112156101e6575f916100bd83923690602481600401359101610384565b906100ff73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163314610426565b82602083519301915af11561011057005b3d61080081116101dd575b60c460405160208382010160405282815260208101925f843e7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f6040519485937f65c8fd4d0000000000000000000000000000000000000000000000000000000085525f6004860152606060248601528260648601527f4141313320454950373730322073656e64657220696e6974206661696c656400608486015260a060448601525180918160a48701528686015e5f85828601015201168101030190fd5b5061080061011b565b5f80fd5b346101e6575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101e657602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b346101e65760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101e65760043567ffffffffffffffff81116101e657366023820112156101e65780600401359067ffffffffffffffff82116101e65736602483830101116101e6575f9161030873ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163314610426565b806014116101e6576020916103455f927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec36910160388401610384565b90826024858451940192013560601c5af161037c575b60209073ffffffffffffffffffffffffffffffffffffffff60405191168152f35b505f5161035b565b92919267ffffffffffffffff82116103f957604051917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f81601f8401160116830183811067ffffffffffffffff8211176103f9576040528294818452818301116101e6578281602093845f960137010152565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b1561042d57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602060248201527f414139372073686f756c642063616c6c2066726f6d20456e747279506f696e746044820152fdfea26469706673582212206423798798d408242e814ed5c031f1afcdccad1146c1c11fab88cce1fdaa4c4a64736f6c634300081c0033"; +address constant ENTRYPOINT_0_8 = 0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108; +address constant DETERMINISTIC_DEPLOYER = 0x4e59b44847b379578588920cA78FbF26c0B4956C; + +library EntryPointLib { + function deploy() internal returns (IEntryPoint) { + (bool success,) = DETERMINISTIC_DEPLOYER.call(ENTRYPOINT_0_8_INITCODE); + require(success); + return IEntryPoint(payable(ENTRYPOINT_0_8)); + } +} From 788512a1a30880fc76175d152dd2c98d1846e7d3 Mon Sep 17 00:00:00 2001 From: leekt Date: Sat, 17 May 2025 00:00:55 +0900 Subject: [PATCH 005/121] execution manager done --- src/Kernel | 0 src/Kernel.sol | 12 ++--- src/Lib4337.sol | 54 +++++++++++++++++++ src/core/ExecutionManager.sol | 99 +++++++++++++++++++++++++++++++++++ 4 files changed, 159 insertions(+), 6 deletions(-) delete mode 100644 src/Kernel create mode 100644 src/Lib4337.sol create mode 100644 src/core/ExecutionManager.sol diff --git a/src/Kernel b/src/Kernel deleted file mode 100644 index e69de29b..00000000 diff --git a/src/Kernel.sol b/src/Kernel.sol index 5181d830..7c085b00 100644 --- a/src/Kernel.sol +++ b/src/Kernel.sol @@ -6,12 +6,13 @@ import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOper import {IValidator} from "./interfaces/IERC7579Modules.sol"; import "./types/Types.sol"; import {ModuleManager, Install} from "./core/ModuleManager.sol"; -import {ValidationManager} from "./core/ValidationManager.sol"; +import {ExecutionManager} from "./core/ExecutionManager.sol"; import {EIP712} from "solady/utils/EIP712.sol"; +import {Lib4337} from "./Lib4337.sol"; import "./types/Error.sol"; import "./types/Events.sol"; -contract Kernel is ValidationManager, ModuleManager, EIP712 { +contract Kernel is ModuleManager, ExecutionManager, EIP712 { IEntryPoint immutable entryPoint; error Unauthorized(); @@ -65,8 +66,9 @@ contract Kernel is ValidationManager, ModuleManager, EIP712 { } signature = sig.userOpSignature; _verifyInstallSignature(enableReplayable, sig.packages, sig.enableSignature); + _install(sig.packages); } - opHash = userOpHash; + opHash = isReplayable(vMode) ? Lib4337.chainAgnosticUserOpHash(msg.sender, userOp) : userOpHash; } function isValidSignature(bytes32 hash, bytes calldata signature) external view returns (bytes4) {} @@ -84,8 +86,6 @@ contract Kernel is ValidationManager, ModuleManager, EIP712 { _execute(mode, executionData); } - function _execute(bytes32 mode, bytes calldata executionData) internal {} - /// management struct InstallModuleDataFormat { bytes installData; @@ -100,8 +100,8 @@ contract Kernel is ValidationManager, ModuleManager, EIP712 { _installModule(moduleType, module, imdf.installData, imdf.internalData); } - // NOTE : this ONLY allows root signature + // NOTE : this ONLY allows root signature function installModule(bool replayable, Install[] calldata packages, bytes calldata signature) external { require(_verifyInstallSignature(replayable, packages, signature), InstallSignatureVerificationFailed()); _install(packages); diff --git a/src/Lib4337.sol b/src/Lib4337.sol new file mode 100644 index 00000000..3518983a --- /dev/null +++ b/src/Lib4337.sol @@ -0,0 +1,54 @@ +pragma solidity ^0.8.0; + +import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; +import {UserOperationLib} from "account-abstraction/core/UserOperationLib.sol"; +import {Eip7702Support} from "account-abstraction/core/Eip7702Support.sol"; +interface IERC5267 { + function eip712Domain() + external + view + returns ( + bytes1 fields, + string memory name, + string memory version, + uint256 chainId, + address verifyingContract, + bytes32 salt, + uint256[] memory extensions + ); +} + +library Lib4337 { + bytes32 internal constant _DOMAIN_TYPEHASH_SANS_CHAIN_ID = + 0x91ab3d17e3a50a9d89e63fd30b92be7f5336b03b287bb946787a83a9d62a2766; + function chainAgnosticUserOpHash(address ep, PackedUserOperation calldata userOp) public view returns(bytes32) { + bytes32 overrideInitCodeHash = Eip7702Support._getEip7702InitCodeHashOverride(userOp); + return + _hashTypedDataSansChainId(ep, UserOperationLib.hash(userOp, overrideInitCodeHash)); + } + + /// @dev Variant of `_hashTypedData` that excludes the chain ID. + /// Included for the niche use case of cross-chain workflows. + function _hashTypedDataSansChainId(address addr, bytes32 structHash) + internal + view + returns (bytes32 digest) + { + (,string memory name, string memory version, , , , ) = IERC5267(addr).eip712Domain(); + /// @solidity memory-safe-assembly + assembly { + let m := mload(0x40) // Load the free memory pointer. + mstore(0x00, _DOMAIN_TYPEHASH_SANS_CHAIN_ID) + mstore(0x20, keccak256(add(name, 0x20), mload(name))) + mstore(0x40, keccak256(add(version, 0x20), mload(version))) + mstore(0x60, addr) + // Compute the digest. + mstore(0x20, keccak256(0x00, 0x80)) // Store the domain separator. + mstore(0x00, 0x1901) // Store "\x19\x01". + mstore(0x40, structHash) // Store the struct hash. + digest := keccak256(0x1e, 0x42) + mstore(0x40, m) // Restore the free memory pointer. + mstore(0x60, 0) // Restore the zero pointer. + } + } +} diff --git a/src/core/ExecutionManager.sol b/src/core/ExecutionManager.sol new file mode 100644 index 00000000..8ddb389f --- /dev/null +++ b/src/core/ExecutionManager.sol @@ -0,0 +1,99 @@ +pragma solidity ^0.8.0; + +import {LibERC7579} from "solady/accounts/LibERC7579.sol"; + +contract ExecutionManager { + error NotSupportedCallType(); + error NotSupportedExecType(); + function _execute(bytes32 mode, bytes calldata executionData) internal { + bytes1 callType = LibERC7579.getCallType(mode); + bytes1 execType = LibERC7579.getExecType(mode); + function(bytes memory) onRevert; + if(execType == LibERC7579.EXECTYPE_DEFAULT) { + onRevert = _onRevertThrow; + } else if(execType == LibERC7579.EXECTYPE_TRY) { + onRevert = _onRevertSilent; + } else { + revert NotSupportedExecType(); + } + + function(bytes calldata, function(bytes memory)) executeFunction; + if(callType == LibERC7579.CALLTYPE_SINGLE) { + executeFunction = _executeCall; + } else if(callType == LibERC7579.CALLTYPE_BATCH) { + executeFunction = _executeBatchCall; + } else if(callType == LibERC7579.CALLTYPE_DELEGATECALL) { + executeFunction = _executeDelegateCall; +// } else if(callType == LibERC7579.CALLTYPE_STATICCALL) { TODO: let's deal with static call later +// executeFunction = _executeStaticCall; + } else { + revert NotSupportedCallType(); + } + } + + function _executeCall(bytes calldata executionData, function(bytes memory) onRevert) internal { + (address target, uint256 value, bytes calldata data) = LibERC7579.decodeSingle(executionData); + (bool success, bytes memory res) = _call(target, value, data); + if(!success) { + onRevert(res); + } + } + + function _executeDelegateCall(bytes calldata executionData, function(bytes memory) onRevert) internal { + (address delegate, bytes calldata data) = LibERC7579.decodeDelegate(executionData); + (bool success, bytes memory res) = _delegateCall(delegate, data); + if(!success) { + onRevert(res); + } + } + + function _executeBatchCall(bytes calldata executionData, function(bytes memory) onRevert) internal { + bytes32[] calldata pointers = LibERC7579.decodeBatch(executionData); + uint256 length = pointers.length; + bytes[] memory result = new bytes[](length); + unchecked { + for (uint256 i; i < length; i++) { + (address target, uint256 value, bytes calldata data) = LibERC7579.getExecution(pointers, i); + (bool success, bytes memory ret) = _call(target, value, data); + onRevert(ret); + } + } + } + + function _onRevertThrow(bytes memory revertData) internal { + uint256 length = revertData.length; + assembly { + revert(revertData, length) + } + } + + function _onRevertSilent(bytes memory revertData) internal { + } + + function _call(address target, uint256 value, bytes calldata callData) internal returns(bool success, bytes memory result){ + /// @solidity memory-safe-assembly + assembly { + result := mload(0x40) + calldatacopy(result, callData.offset, callData.length) + success := call(gas(), target, value, result, callData.length, codesize(), 0x00) + mstore(result, returndatasize()) // Store the length. + let o := add(result, 0x20) + returndatacopy(o, 0x00, returndatasize()) // Copy the returndata. + mstore(0x40, add(o, returndatasize())) // Allocate the memory. + } + } + + function _delegateCall(address delegate, bytes calldata callData) internal returns(bool success, bytes memory result){ + /// @solidity memory-safe-assembly + assembly { + result := mload(0x40) + calldatacopy(result, callData.offset, callData.length) + // Forwards the `data` to `delegate` via delegatecall. + success := delegatecall(gas(), delegate, result, callData.length, codesize(), 0x00) + mstore(result, returndatasize()) // Store the length. + let o := add(result, 0x20) + returndatacopy(o, 0x00, returndatasize()) // Copy the returndata. + mstore(0x40, add(o, returndatasize())) // Allocate the memory. + } + } +} From 23c301784038ea106caefb5a43c0ae0e29575a73 Mon Sep 17 00:00:00 2001 From: leekt Date: Thu, 22 May 2025 05:44:53 +0900 Subject: [PATCH 006/121] Execution done --- coverage/amber.png | Bin 0 -> 141 bytes coverage/cmd_line | 1 + coverage/emerald.png | Bin 0 -> 141 bytes coverage/gcov.css | 1101 +++++++++++++++++ coverage/glass.png | Bin 0 -> 167 bytes coverage/index-sort-f.html | 141 +++ coverage/index-sort-l.html | 141 +++ coverage/index.html | 141 +++ coverage/ruby.png | Bin 0 -> 141 bytes coverage/snow.png | Bin 0 -> 141 bytes coverage/src/Kernel.sol.func-c.html | 173 +++ coverage/src/Kernel.sol.func.html | 173 +++ coverage/src/Kernel.sol.gcov.html | 254 ++++ coverage/src/KernelFactory.sol.func-c.html | 96 ++ coverage/src/KernelFactory.sol.func.html | 96 ++ coverage/src/KernelFactory.sol.gcov.html | 104 ++ coverage/src/Lib4337.sol.func-c.html | 89 ++ coverage/src/Lib4337.sol.func.html | 89 ++ coverage/src/Lib4337.sol.gcov.html | 130 ++ .../src/core/ExecutionManager.sol.func-c.html | 131 ++ .../src/core/ExecutionManager.sol.func.html | 131 ++ .../src/core/ExecutionManager.sol.gcov.html | 168 +++ .../src/core/ExecutorManager.sol.func-c.html | 110 ++ .../src/core/ExecutorManager.sol.func.html | 110 ++ .../src/core/ExecutorManager.sol.gcov.html | 119 ++ coverage/src/core/HookManager.sol.func-c.html | 103 ++ coverage/src/core/HookManager.sol.func.html | 103 ++ coverage/src/core/HookManager.sol.gcov.html | 113 ++ .../src/core/ModuleManager.sol.func-c.html | 117 ++ coverage/src/core/ModuleManager.sol.func.html | 117 ++ coverage/src/core/ModuleManager.sol.gcov.html | 173 +++ .../src/core/SelectorManager.sol.func-c.html | 103 ++ .../src/core/SelectorManager.sol.func.html | 103 ++ .../src/core/SelectorManager.sol.gcov.html | 127 ++ .../core/ValidationManager.sol.func-c.html | 166 +++ .../src/core/ValidationManager.sol.func.html | 166 +++ .../src/core/ValidationManager.sol.gcov.html | 240 ++++ coverage/src/core/index-sort-f.html | 165 +++ coverage/src/core/index-sort-l.html | 165 +++ coverage/src/core/index.html | 165 +++ coverage/src/index-sort-f.html | 129 ++ coverage/src/index-sort-l.html | 129 ++ coverage/src/index.html | 129 ++ coverage/test/Kernel.t.sol.func-c.html | 110 ++ coverage/test/Kernel.t.sol.func.html | 110 ++ coverage/test/Kernel.t.sol.gcov.html | 284 +++++ coverage/test/index-sort-f.html | 105 ++ coverage/test/index-sort-l.html | 105 ++ coverage/test/index.html | 105 ++ .../test/utils/EntryPointLib.sol.func-c.html | 82 ++ .../test/utils/EntryPointLib.sol.func.html | 82 ++ .../test/utils/EntryPointLib.sol.gcov.html | 92 ++ coverage/test/utils/index-sort-f.html | 105 ++ coverage/test/utils/index-sort-l.html | 105 ++ coverage/test/utils/index.html | 105 ++ coverage/updown.png | Bin 0 -> 117 bytes lcov.info | 626 ++++++++++ src/Kernel.sol | 80 +- src/KernelFactory.sol | 11 +- src/core/ExecutionManager.sol | 65 +- src/core/ExecutorManager.sol | 43 + src/core/HookManager.sol | 37 + src/core/ModuleManager.sol | 43 +- src/core/SelectorManager.sol | 51 + src/core/ValidationManager.sol | 99 +- src/types/Constants.sol | 29 +- src/types/Error.sol | 8 + src/types/Structs.sol | 14 + src/types/Types.sol | 31 + test/Kernel.t.sol | 166 ++- 70 files changed, 8618 insertions(+), 86 deletions(-) create mode 100644 coverage/amber.png create mode 100644 coverage/cmd_line create mode 100644 coverage/emerald.png create mode 100644 coverage/gcov.css create mode 100644 coverage/glass.png create mode 100644 coverage/index-sort-f.html create mode 100644 coverage/index-sort-l.html create mode 100644 coverage/index.html create mode 100644 coverage/ruby.png create mode 100644 coverage/snow.png create mode 100644 coverage/src/Kernel.sol.func-c.html create mode 100644 coverage/src/Kernel.sol.func.html create mode 100644 coverage/src/Kernel.sol.gcov.html create mode 100644 coverage/src/KernelFactory.sol.func-c.html create mode 100644 coverage/src/KernelFactory.sol.func.html create mode 100644 coverage/src/KernelFactory.sol.gcov.html create mode 100644 coverage/src/Lib4337.sol.func-c.html create mode 100644 coverage/src/Lib4337.sol.func.html create mode 100644 coverage/src/Lib4337.sol.gcov.html create mode 100644 coverage/src/core/ExecutionManager.sol.func-c.html create mode 100644 coverage/src/core/ExecutionManager.sol.func.html create mode 100644 coverage/src/core/ExecutionManager.sol.gcov.html create mode 100644 coverage/src/core/ExecutorManager.sol.func-c.html create mode 100644 coverage/src/core/ExecutorManager.sol.func.html create mode 100644 coverage/src/core/ExecutorManager.sol.gcov.html create mode 100644 coverage/src/core/HookManager.sol.func-c.html create mode 100644 coverage/src/core/HookManager.sol.func.html create mode 100644 coverage/src/core/HookManager.sol.gcov.html create mode 100644 coverage/src/core/ModuleManager.sol.func-c.html create mode 100644 coverage/src/core/ModuleManager.sol.func.html create mode 100644 coverage/src/core/ModuleManager.sol.gcov.html create mode 100644 coverage/src/core/SelectorManager.sol.func-c.html create mode 100644 coverage/src/core/SelectorManager.sol.func.html create mode 100644 coverage/src/core/SelectorManager.sol.gcov.html create mode 100644 coverage/src/core/ValidationManager.sol.func-c.html create mode 100644 coverage/src/core/ValidationManager.sol.func.html create mode 100644 coverage/src/core/ValidationManager.sol.gcov.html create mode 100644 coverage/src/core/index-sort-f.html create mode 100644 coverage/src/core/index-sort-l.html create mode 100644 coverage/src/core/index.html create mode 100644 coverage/src/index-sort-f.html create mode 100644 coverage/src/index-sort-l.html create mode 100644 coverage/src/index.html create mode 100644 coverage/test/Kernel.t.sol.func-c.html create mode 100644 coverage/test/Kernel.t.sol.func.html create mode 100644 coverage/test/Kernel.t.sol.gcov.html create mode 100644 coverage/test/index-sort-f.html create mode 100644 coverage/test/index-sort-l.html create mode 100644 coverage/test/index.html create mode 100644 coverage/test/utils/EntryPointLib.sol.func-c.html create mode 100644 coverage/test/utils/EntryPointLib.sol.func.html create mode 100644 coverage/test/utils/EntryPointLib.sol.gcov.html create mode 100644 coverage/test/utils/index-sort-f.html create mode 100644 coverage/test/utils/index-sort-l.html create mode 100644 coverage/test/utils/index.html create mode 100644 coverage/updown.png create mode 100644 lcov.info create mode 100644 src/core/ExecutorManager.sol create mode 100644 src/core/HookManager.sol create mode 100644 src/core/SelectorManager.sol create mode 100644 src/types/Structs.sol diff --git a/coverage/amber.png b/coverage/amber.png new file mode 100644 index 0000000000000000000000000000000000000000..2cab170d8359081983a4e343848dfe06bc490f12 GIT binary patch literal 141 zcmeAS@N?(olHy`uVBq!ia0vp^j3CU&3?x-=hn)ga>?NMQuI!iC1^G2tW}LqE04T&+ z;1OBOz`!j8!i<;h*8KqrvZOouIx;Y9?C1WI$O`1M1^9%x{(levWG?NMQuI!iC1^Jb!lvI6;R0X`wF(yt=9xVZRt1vCRixIA4P dLn>}1Cji+@42)0J?}79&c)I$ztaD0e0sy@GAL0N2 literal 0 HcmV?d00001 diff --git a/coverage/gcov.css b/coverage/gcov.css new file mode 100644 index 00000000..6c23ba93 --- /dev/null +++ b/coverage/gcov.css @@ -0,0 +1,1101 @@ +/* All views: initial background and text color */ +body +{ + color: #000000; + background-color: #ffffff; +} + +/* All views: standard link format*/ +a:link +{ + color: #284fa8; + text-decoration: underline; +} + +/* All views: standard link - visited format */ +a:visited +{ + color: #00cb40; + text-decoration: underline; +} + +/* All views: standard link - activated format */ +a:active +{ + color: #ff0040; + text-decoration: underline; +} + +/* All views: main title format */ +td.title +{ + text-align: center; + padding-bottom: 10px; + font-family: sans-serif; + font-size: 20pt; + font-style: italic; + font-weight: bold; +} +/* "Line coverage date bins" leader */ +td.subTableHeader +{ + text-align: center; + padding-bottom: 6px; + font-family: sans-serif; + font-weight: bold; + vertical-align: center; +} + +/* All views: header item format */ +td.headerItem +{ + text-align: right; + padding-right: 6px; + font-family: sans-serif; + font-weight: bold; + vertical-align: top; + white-space: nowrap; +} + +/* All views: header item value format */ +td.headerValue +{ + text-align: left; + color: #284fa8; + font-family: sans-serif; + font-weight: bold; + white-space: nowrap; +} + +/* All views: header item coverage table heading */ +td.headerCovTableHead +{ + text-align: center; + padding-right: 6px; + padding-left: 6px; + padding-bottom: 0px; + font-family: sans-serif; + white-space: nowrap; +} + +/* All views: header item coverage table entry */ +td.headerCovTableEntry +{ + text-align: right; + color: #284fa8; + font-family: sans-serif; + font-weight: bold; + white-space: nowrap; + padding-left: 12px; + padding-right: 4px; + background-color: #dae7fe; +} + +/* All views: header item coverage table entry for high coverage rate */ +td.headerCovTableEntryHi +{ + text-align: right; + color: #000000; + font-family: sans-serif; + font-weight: bold; + white-space: nowrap; + padding-left: 12px; + padding-right: 4px; + background-color: #a7fc9d; +} + +/* All views: header item coverage table entry for medium coverage rate */ +td.headerCovTableEntryMed +{ + text-align: right; + color: #000000; + font-family: sans-serif; + font-weight: bold; + white-space: nowrap; + padding-left: 12px; + padding-right: 4px; + background-color: #ffea20; +} + +/* All views: header item coverage table entry for ow coverage rate */ +td.headerCovTableEntryLo +{ + text-align: right; + color: #000000; + font-family: sans-serif; + font-weight: bold; + white-space: nowrap; + padding-left: 12px; + padding-right: 4px; + background-color: #ff0000; +} + +/* All views: header legend value for legend entry */ +td.headerValueLeg +{ + text-align: left; + color: #000000; + font-family: sans-serif; + font-size: 80%; + white-space: nowrap; + padding-top: 4px; +} + +/* All views: color of horizontal ruler */ +td.ruler +{ + background-color: #6688d4; +} + +/* All views: version string format */ +td.versionInfo +{ + text-align: center; + padding-top: 2px; + font-family: sans-serif; + font-style: italic; +} + +/* Directory view/File view (all)/Test case descriptions: + table headline format */ +td.tableHead +{ + text-align: center; + color: #ffffff; + background-color: #6688d4; + font-family: sans-serif; + font-size: 120%; + font-weight: bold; + white-space: nowrap; + padding-left: 4px; + padding-right: 4px; +} + +span.tableHeadSort +{ + padding-right: 4px; +} + +/* Directory view/File view (all): filename entry format */ +td.coverFile +{ + text-align: left; + padding-left: 10px; + padding-right: 20px; + color: #284fa8; + background-color: #dae7fe; + font-family: monospace; +} + +/* Directory view/File view (all): directory name entry format */ +td.coverDirectory +{ + text-align: left; + padding-left: 10px; + padding-right: 20px; + color: #284fa8; + background-color: #b8d0ff; + font-family: monospace; +} + +/* Directory view/File view (all): filename entry format */ +td.overallOwner +{ + text-align: center; + font-weight: bold; + font-family: sans-serif; + background-color: #dae7fe; + padding-right: 10px; + padding-left: 10px; +} + +/* Directory view/File view (all): filename entry format */ +td.ownerName +{ + text-align: right; + font-style: italic; + font-family: sans-serif; + background-color: #E5DBDB; + padding-right: 10px; + padding-left: 20px; +} + +/* Directory view/File view (all): bar-graph entry format*/ +td.coverBar +{ + padding-left: 10px; + padding-right: 10px; + background-color: #dae7fe; +} + +/* Directory view/File view (all): bar-graph entry format*/ +td.owner_coverBar +{ + padding-left: 10px; + padding-right: 10px; + background-color: #E5DBDB; +} + +/* Directory view/File view (all): bar-graph outline color */ +td.coverBarOutline +{ + background-color: #000000; +} + +/* Directory view/File view (all): percentage entry for files with + high coverage rate */ +td.coverPerHi +{ + text-align: right; + padding-left: 10px; + padding-right: 10px; + background-color: #a7fc9d; + font-weight: bold; + font-family: sans-serif; +} + +/* 'owner' entry: slightly lighter color than 'coverPerHi' */ +td.owner_coverPerHi +{ + text-align: right; + padding-left: 10px; + padding-right: 10px; + background-color: #82E0AA; + font-weight: bold; + font-family: sans-serif; +} + +/* Directory view/File view (all): line count entry */ +td.coverNumDflt +{ + text-align: right; + padding-left: 10px; + padding-right: 10px; + background-color: #dae7fe; + white-space: nowrap; + font-family: sans-serif; +} + +/* td background color and font for the 'owner' section of the table */ +td.ownerTla +{ + text-align: right; + padding-left: 10px; + padding-right: 10px; + background-color: #E5DBDB; + white-space: nowrap; + font-family: sans-serif; + font-style: italic; +} + +/* Directory view/File view (all): line count entry for files with + high coverage rate */ +td.coverNumHi +{ + text-align: right; + padding-left: 10px; + padding-right: 10px; + background-color: #a7fc9d; + white-space: nowrap; + font-family: sans-serif; +} + +td.owner_coverNumHi +{ + text-align: right; + padding-left: 10px; + padding-right: 10px; + background-color: #82E0AA; + white-space: nowrap; + font-family: sans-serif; +} + +/* Directory view/File view (all): percentage entry for files with + medium coverage rate */ +td.coverPerMed +{ + text-align: right; + padding-left: 10px; + padding-right: 10px; + background-color: #ffea20; + font-weight: bold; + font-family: sans-serif; +} + +td.owner_coverPerMed +{ + text-align: right; + padding-left: 10px; + padding-right: 10px; + background-color: #F9E79F; + font-weight: bold; + font-family: sans-serif; +} + +/* Directory view/File view (all): line count entry for files with + medium coverage rate */ +td.coverNumMed +{ + text-align: right; + padding-left: 10px; + padding-right: 10px; + background-color: #ffea20; + white-space: nowrap; + font-family: sans-serif; +} + +td.owner_coverNumMed +{ + text-align: right; + padding-left: 10px; + padding-right: 10px; + background-color: #F9E79F; + white-space: nowrap; + font-family: sans-serif; +} + +/* Directory view/File view (all): percentage entry for files with + low coverage rate */ +td.coverPerLo +{ + text-align: right; + padding-left: 10px; + padding-right: 10px; + background-color: #ff0000; + font-weight: bold; + font-family: sans-serif; +} + +td.owner_coverPerLo +{ + text-align: right; + padding-left: 10px; + padding-right: 10px; + background-color: #EC7063; + font-weight: bold; + font-family: sans-serif; +} + +/* Directory view/File view (all): line count entry for files with + low coverage rate */ +td.coverNumLo +{ + text-align: right; + padding-left: 10px; + padding-right: 10px; + background-color: #ff0000; + white-space: nowrap; + font-family: sans-serif; +} + +td.owner_coverNumLo +{ + text-align: right; + padding-left: 10px; + padding-right: 10px; + background-color: #EC7063; + white-space: nowrap; + font-family: sans-serif; +} + +/* File view (all): "show/hide details" link format */ +a.detail:link +{ + color: #b8d0ff; + font-size:80%; +} + +/* File view (all): "show/hide details" link - visited format */ +a.detail:visited +{ + color: #b8d0ff; + font-size:80%; +} + +/* File view (all): "show/hide details" link - activated format */ +a.detail:active +{ + color: #ffffff; + font-size:80%; +} + +/* File view (detail): test name entry */ +td.testName +{ + text-align: right; + padding-right: 10px; + background-color: #dae7fe; + font-family: sans-serif; +} + +/* File view (detail): test percentage entry */ +td.testPer +{ + text-align: right; + padding-left: 10px; + padding-right: 10px; + background-color: #dae7fe; + font-family: sans-serif; +} + +/* File view (detail): test lines count entry */ +td.testNum +{ + text-align: right; + padding-left: 10px; + padding-right: 10px; + background-color: #dae7fe; + font-family: sans-serif; +} + +/* Test case descriptions: test name format*/ +dt +{ + font-family: sans-serif; + font-weight: bold; +} + +/* Test case descriptions: description table body */ +td.testDescription +{ + padding-top: 10px; + padding-left: 30px; + padding-bottom: 10px; + padding-right: 30px; + background-color: #dae7fe; +} + +/* Source code view: function entry */ +td.coverFn +{ + text-align: left; + padding-left: 10px; + padding-right: 20px; + color: #284fa8; + background-color: #dae7fe; + font-family: monospace; +} + +/* Source code view: function entry zero count*/ +td.coverFnLo +{ + text-align: right; + padding-left: 10px; + padding-right: 10px; + background-color: #ff0000; + font-weight: bold; + font-family: sans-serif; +} + +/* Source code view: function entry nonzero count*/ +td.coverFnHi +{ + text-align: right; + padding-left: 10px; + padding-right: 10px; + background-color: #dae7fe; + font-weight: bold; + font-family: sans-serif; +} + +td.coverFnAlias +{ + text-align: right; + padding-left: 10px; + padding-right: 20px; + color: #284fa8; + /* make this a slightly different color than the leader - otherwise, + otherwise the alias is hard to distinguish in the table */ + background-color: #E5DBDB; /* very light pale grey/blue */ + font-family: monospace; +} + +/* Source code view: function entry zero count*/ +td.coverFnAliasLo +{ + text-align: right; + padding-left: 10px; + padding-right: 10px; + background-color: #EC7063; /* lighter red */ + font-family: sans-serif; +} + +/* Source code view: function entry nonzero count*/ +td.coverFnAliasHi +{ + text-align: right; + padding-left: 10px; + padding-right: 10px; + background-color: #dae7fe; + font-weight: bold; + font-family: sans-serif; +} + +/* Source code view: source code format */ +pre.source +{ + font-family: monospace; + white-space: pre; + margin-top: 2px; +} + +/* elided/removed code */ +span.elidedSource +{ + font-family: sans-serif; + /*font-size: 8pt; */ + font-style: italic; + background-color: lightgrey; +} + +/* Source code view: line number format */ +span.lineNum +{ + background-color: #efe383; +} + +/* Source code view: line number format when there are deleted + lines in the corresponding location */ +span.lineNumWithDelete +{ + foreground-color: #efe383; + background-color: lightgrey; +} + +/* Source code view: format for Cov legend */ +span.coverLegendCov +{ + padding-left: 10px; + padding-right: 10px; + padding-bottom: 2px; + background-color: #cad7fe; +} + +/* Source code view: format for NoCov legend */ +span.coverLegendNoCov +{ + padding-left: 10px; + padding-right: 10px; + padding-bottom: 2px; + background-color: #ff6230; +} + +/* Source code view: format for the source code heading line */ +pre.sourceHeading +{ + white-space: pre; + font-family: monospace; + font-weight: bold; + margin: 0px; +} + +/* All views: header legend value for low rate */ +td.headerValueLegL +{ + font-family: sans-serif; + text-align: center; + white-space: nowrap; + padding-left: 4px; + padding-right: 2px; + background-color: #ff0000; + font-size: 80%; +} + +/* All views: header legend value for med rate */ +td.headerValueLegM +{ + font-family: sans-serif; + text-align: center; + white-space: nowrap; + padding-left: 2px; + padding-right: 2px; + background-color: #ffea20; + font-size: 80%; +} + +/* All views: header legend value for hi rate */ +td.headerValueLegH +{ + font-family: sans-serif; + text-align: center; + white-space: nowrap; + padding-left: 2px; + padding-right: 4px; + background-color: #a7fc9d; + font-size: 80%; +} + +/* All views except source code view: legend format for low coverage */ +span.coverLegendCovLo +{ + padding-left: 10px; + padding-right: 10px; + padding-top: 2px; + background-color: #ff0000; +} + +/* All views except source code view: legend format for med coverage */ +span.coverLegendCovMed +{ + padding-left: 10px; + padding-right: 10px; + padding-top: 2px; + background-color: #ffea20; +} + +/* All views except source code view: legend format for hi coverage */ +span.coverLegendCovHi +{ + padding-left: 10px; + padding-right: 10px; + padding-top: 2px; + background-color: #a7fc9d; +} + +a.branchTla:link +{ + color: #000000; +} + +a.branchTla:visited +{ + color: #000000; +} + +/* Source code view/table entry background: format for lines classified as "Uncovered New Code (+ => 0): +Newly added code is not tested" */ +td.tlaUNC +{ + text-align: right; + background-color: #FF6230; +} +td.tlaBgUNC { + background-color: #FF6230; +} + +/* Source code view/table entry background: format for lines classified as "Uncovered New Code (+ => 0): +Newly added code is not tested" */ +span.tlaUNC +{ + text-align: left; + background-color: #FF6230; +} +span.tlaBgUNC { + background-color: #FF6230; +} +a.tlaBgUNC { + background-color: #FF6230; + color: #000000; +} + +td.headerCovTableHeadUNC { + text-align: center; + padding-right: 6px; + padding-left: 6px; + padding-bottom: 0px; + font-family: sans-serif; + white-space: nowrap; + background-color: #FF6230; +} + +/* Source code view/table entry background: format for lines classified as "Lost Baseline Coverage (1 => 0): +Unchanged code is no longer tested" */ +td.tlaLBC +{ + text-align: right; + background-color: #FF6230; +} +td.tlaBgLBC { + background-color: #FF6230; +} + +/* Source code view/table entry background: format for lines classified as "Lost Baseline Coverage (1 => 0): +Unchanged code is no longer tested" */ +span.tlaLBC +{ + text-align: left; + background-color: #FF6230; +} +span.tlaBgLBC { + background-color: #FF6230; +} +a.tlaBgLBC { + background-color: #FF6230; + color: #000000; +} + +td.headerCovTableHeadLBC { + text-align: center; + padding-right: 6px; + padding-left: 6px; + padding-bottom: 0px; + font-family: sans-serif; + white-space: nowrap; + background-color: #FF6230; +} + +/* Source code view/table entry background: format for lines classified as "Uncovered Included Code (# => 0): +Previously unused code is untested" */ +td.tlaUIC +{ + text-align: right; + background-color: #FF6230; +} +td.tlaBgUIC { + background-color: #FF6230; +} + +/* Source code view/table entry background: format for lines classified as "Uncovered Included Code (# => 0): +Previously unused code is untested" */ +span.tlaUIC +{ + text-align: left; + background-color: #FF6230; +} +span.tlaBgUIC { + background-color: #FF6230; +} +a.tlaBgUIC { + background-color: #FF6230; + color: #000000; +} + +td.headerCovTableHeadUIC { + text-align: center; + padding-right: 6px; + padding-left: 6px; + padding-bottom: 0px; + font-family: sans-serif; + white-space: nowrap; + background-color: #FF6230; +} + +/* Source code view/table entry background: format for lines classified as "Uncovered Baseline Code (0 => 0): +Unchanged code was untested before, is untested now" */ +td.tlaUBC +{ + text-align: right; + background-color: #FF6230; +} +td.tlaBgUBC { + background-color: #FF6230; +} + +/* Source code view/table entry background: format for lines classified as "Uncovered Baseline Code (0 => 0): +Unchanged code was untested before, is untested now" */ +span.tlaUBC +{ + text-align: left; + background-color: #FF6230; +} +span.tlaBgUBC { + background-color: #FF6230; +} +a.tlaBgUBC { + background-color: #FF6230; + color: #000000; +} + +td.headerCovTableHeadUBC { + text-align: center; + padding-right: 6px; + padding-left: 6px; + padding-bottom: 0px; + font-family: sans-serif; + white-space: nowrap; + background-color: #FF6230; +} + +/* Source code view/table entry background: format for lines classified as "Gained Baseline Coverage (0 => 1): +Unchanged code is tested now" */ +td.tlaGBC +{ + text-align: right; + background-color: #CAD7FE; +} +td.tlaBgGBC { + background-color: #CAD7FE; +} + +/* Source code view/table entry background: format for lines classified as "Gained Baseline Coverage (0 => 1): +Unchanged code is tested now" */ +span.tlaGBC +{ + text-align: left; + background-color: #CAD7FE; +} +span.tlaBgGBC { + background-color: #CAD7FE; +} +a.tlaBgGBC { + background-color: #CAD7FE; + color: #000000; +} + +td.headerCovTableHeadGBC { + text-align: center; + padding-right: 6px; + padding-left: 6px; + padding-bottom: 0px; + font-family: sans-serif; + white-space: nowrap; + background-color: #CAD7FE; +} + +/* Source code view/table entry background: format for lines classified as "Gained Included Coverage (# => 1): +Previously unused code is tested now" */ +td.tlaGIC +{ + text-align: right; + background-color: #CAD7FE; +} +td.tlaBgGIC { + background-color: #CAD7FE; +} + +/* Source code view/table entry background: format for lines classified as "Gained Included Coverage (# => 1): +Previously unused code is tested now" */ +span.tlaGIC +{ + text-align: left; + background-color: #CAD7FE; +} +span.tlaBgGIC { + background-color: #CAD7FE; +} +a.tlaBgGIC { + background-color: #CAD7FE; + color: #000000; +} + +td.headerCovTableHeadGIC { + text-align: center; + padding-right: 6px; + padding-left: 6px; + padding-bottom: 0px; + font-family: sans-serif; + white-space: nowrap; + background-color: #CAD7FE; +} + +/* Source code view/table entry background: format for lines classified as "Gained New Coverage (+ => 1): +Newly added code is tested" */ +td.tlaGNC +{ + text-align: right; + background-color: #CAD7FE; +} +td.tlaBgGNC { + background-color: #CAD7FE; +} + +/* Source code view/table entry background: format for lines classified as "Gained New Coverage (+ => 1): +Newly added code is tested" */ +span.tlaGNC +{ + text-align: left; + background-color: #CAD7FE; +} +span.tlaBgGNC { + background-color: #CAD7FE; +} +a.tlaBgGNC { + background-color: #CAD7FE; + color: #000000; +} + +td.headerCovTableHeadGNC { + text-align: center; + padding-right: 6px; + padding-left: 6px; + padding-bottom: 0px; + font-family: sans-serif; + white-space: nowrap; + background-color: #CAD7FE; +} + +/* Source code view/table entry background: format for lines classified as "Covered Baseline Code (1 => 1): +Unchanged code was tested before and is still tested" */ +td.tlaCBC +{ + text-align: right; + background-color: #CAD7FE; +} +td.tlaBgCBC { + background-color: #CAD7FE; +} + +/* Source code view/table entry background: format for lines classified as "Covered Baseline Code (1 => 1): +Unchanged code was tested before and is still tested" */ +span.tlaCBC +{ + text-align: left; + background-color: #CAD7FE; +} +span.tlaBgCBC { + background-color: #CAD7FE; +} +a.tlaBgCBC { + background-color: #CAD7FE; + color: #000000; +} + +td.headerCovTableHeadCBC { + text-align: center; + padding-right: 6px; + padding-left: 6px; + padding-bottom: 0px; + font-family: sans-serif; + white-space: nowrap; + background-color: #CAD7FE; +} + +/* Source code view/table entry background: format for lines classified as "Excluded Uncovered Baseline (0 => #): +Previously untested code is unused now" */ +td.tlaEUB +{ + text-align: right; + background-color: #FFFFFF; +} +td.tlaBgEUB { + background-color: #FFFFFF; +} + +/* Source code view/table entry background: format for lines classified as "Excluded Uncovered Baseline (0 => #): +Previously untested code is unused now" */ +span.tlaEUB +{ + text-align: left; + background-color: #FFFFFF; +} +span.tlaBgEUB { + background-color: #FFFFFF; +} +a.tlaBgEUB { + background-color: #FFFFFF; + color: #000000; +} + +td.headerCovTableHeadEUB { + text-align: center; + padding-right: 6px; + padding-left: 6px; + padding-bottom: 0px; + font-family: sans-serif; + white-space: nowrap; + background-color: #FFFFFF; +} + +/* Source code view/table entry background: format for lines classified as "Excluded Covered Baseline (1 => #): +Previously tested code is unused now" */ +td.tlaECB +{ + text-align: right; + background-color: #FFFFFF; +} +td.tlaBgECB { + background-color: #FFFFFF; +} + +/* Source code view/table entry background: format for lines classified as "Excluded Covered Baseline (1 => #): +Previously tested code is unused now" */ +span.tlaECB +{ + text-align: left; + background-color: #FFFFFF; +} +span.tlaBgECB { + background-color: #FFFFFF; +} +a.tlaBgECB { + background-color: #FFFFFF; + color: #000000; +} + +td.headerCovTableHeadECB { + text-align: center; + padding-right: 6px; + padding-left: 6px; + padding-bottom: 0px; + font-family: sans-serif; + white-space: nowrap; + background-color: #FFFFFF; +} + +/* Source code view/table entry background: format for lines classified as "Deleted Uncovered Baseline (0 => -): +Previously untested code has been deleted" */ +td.tlaDUB +{ + text-align: right; + background-color: #FFFFFF; +} +td.tlaBgDUB { + background-color: #FFFFFF; +} + +/* Source code view/table entry background: format for lines classified as "Deleted Uncovered Baseline (0 => -): +Previously untested code has been deleted" */ +span.tlaDUB +{ + text-align: left; + background-color: #FFFFFF; +} +span.tlaBgDUB { + background-color: #FFFFFF; +} +a.tlaBgDUB { + background-color: #FFFFFF; + color: #000000; +} + +td.headerCovTableHeadDUB { + text-align: center; + padding-right: 6px; + padding-left: 6px; + padding-bottom: 0px; + font-family: sans-serif; + white-space: nowrap; + background-color: #FFFFFF; +} + +/* Source code view/table entry background: format for lines classified as "Deleted Covered Baseline (1 => -): +Previously tested code has been deleted" */ +td.tlaDCB +{ + text-align: right; + background-color: #FFFFFF; +} +td.tlaBgDCB { + background-color: #FFFFFF; +} + +/* Source code view/table entry background: format for lines classified as "Deleted Covered Baseline (1 => -): +Previously tested code has been deleted" */ +span.tlaDCB +{ + text-align: left; + background-color: #FFFFFF; +} +span.tlaBgDCB { + background-color: #FFFFFF; +} +a.tlaBgDCB { + background-color: #FFFFFF; + color: #000000; +} + +td.headerCovTableHeadDCB { + text-align: center; + padding-right: 6px; + padding-left: 6px; + padding-bottom: 0px; + font-family: sans-serif; + white-space: nowrap; + background-color: #FFFFFF; +} + +/* Source code view: format for date/owner bin that is not hit */ +span.missBins +{ + background-color: #ff0000 /* red */ +} diff --git a/coverage/glass.png b/coverage/glass.png new file mode 100644 index 0000000000000000000000000000000000000000..e1abc00680a3093c49fdb775ae6bdb6764c95af2 GIT binary patch literal 167 zcmeAS@N?(olHy`uVBq!ia0vp^j3CU&3?x-=hn)gaEa{HEjtmSN`?>!lvI6;R0X`wF z|Ns97GD8ntt^-nxB|(0{3=Yq3q=7g|-tI089jvk*Kn`btM`SSr1Gf+eGhVt|_XjA* zUgGKN%6^Gmn4d%Ph(nkFP>9RZ#WAE}PI3Z}&BVayv3^M*kj3EX>gTe~DWM4f=_Dpv literal 0 HcmV?d00001 diff --git a/coverage/index-sort-f.html b/coverage/index-sort-f.html new file mode 100644 index 00000000..1688fa01 --- /dev/null +++ b/coverage/index-sort-f.html @@ -0,0 +1,141 @@ + + + + + + + LCOV - lcov.info + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top levelCoverageTotalHit
Test:lcov.infoLines:37.1 %307114
Test Date:2025-05-22 05:44:20Functions:46.2 %6530
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Directory Sort by file nameLine Coverage Sort by line coverageFunction Coverage Sort by function coverage
Rate Total Hit Rate Total Hit
src/ +
19.2%19.2%
+
19.2 %991936.8 %197
src/core/ +
42.5%42.5%
+
42.5 %1938245.0 %4018
test/ +
81.8%81.8%
+
81.8 %11980.0 %54
test/utils/ +
100.0%
+
100.0 %44100.0 %11
+
+
+ + + + +
Generated by: LCOV version 2.1-1
+
+ + + diff --git a/coverage/index-sort-l.html b/coverage/index-sort-l.html new file mode 100644 index 00000000..4c40c775 --- /dev/null +++ b/coverage/index-sort-l.html @@ -0,0 +1,141 @@ + + + + + + + LCOV - lcov.info + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top levelCoverageTotalHit
Test:lcov.infoLines:37.1 %307114
Test Date:2025-05-22 05:44:20Functions:46.2 %6530
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Directory Sort by file nameLine Coverage Sort by line coverageFunction Coverage Sort by function coverage
Rate Total Hit Rate Total Hit
src/ +
19.2%19.2%
+
19.2 %991936.8 %197
src/core/ +
42.5%42.5%
+
42.5 %1938245.0 %4018
test/ +
81.8%81.8%
+
81.8 %11980.0 %54
test/utils/ +
100.0%
+
100.0 %44100.0 %11
+
+
+ + + + +
Generated by: LCOV version 2.1-1
+
+ + + diff --git a/coverage/index.html b/coverage/index.html new file mode 100644 index 00000000..7207c67c --- /dev/null +++ b/coverage/index.html @@ -0,0 +1,141 @@ + + + + + + + LCOV - lcov.info + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top levelCoverageTotalHit
Test:lcov.infoLines:37.1 %307114
Test Date:2025-05-22 05:44:20Functions:46.2 %6530
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Directory Sort by file nameLine Coverage Sort by line coverageFunction Coverage Sort by function coverage
Rate Total Hit Rate Total Hit
src/ +
19.2%19.2%
+
19.2 %991936.8 %197
src/core/ +
42.5%42.5%
+
42.5 %1938245.0 %4018
test/ +
81.8%81.8%
+
81.8 %11980.0 %54
test/utils/ +
100.0%
+
100.0 %44100.0 %11
+
+
+ + + + +
Generated by: LCOV version 2.1-1
+
+ + + diff --git a/coverage/ruby.png b/coverage/ruby.png new file mode 100644 index 0000000000000000000000000000000000000000..991b6d4ec9e78be165e3ef757eed1aada287364d GIT binary patch literal 141 zcmeAS@N?(olHy`uVBq!ia0vp^j3CU&3?x-=hn)ga>?NMQuI!iC1^FceV#7`HfI^%F z9+AZi4BSE>%y{W;-5;PJOS+@4BLl<6e(pbstUx|nfKQ0)e^Y%R^MdiLxj>4`)5S5Q b;#P73kj=!v_*DHKNFRfztDnm{r-UW|iOwIS literal 0 HcmV?d00001 diff --git a/coverage/snow.png b/coverage/snow.png new file mode 100644 index 0000000000000000000000000000000000000000..2cdae107fceec6e7f02ac7acb4a34a82a540caa5 GIT binary patch literal 141 zcmeAS@N?(olHy`uVBq!ia0vp^j3CU&3?x-=hn)ga>?NMQuI!iC1^MM!lvI6;R0X`wF|Ns97GD8ntt^-nBo-U3d c6}OTTfNUlP#;5A{K>8RwUHx3vIVCg!071?oo&W#< literal 0 HcmV?d00001 diff --git a/coverage/src/Kernel.sol.func-c.html b/coverage/src/Kernel.sol.func-c.html new file mode 100644 index 00000000..ec9b1bc4 --- /dev/null +++ b/coverage/src/Kernel.sol.func-c.html @@ -0,0 +1,173 @@ + + + + + + + LCOV - lcov.info - src/Kernel.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - src - Kernel.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:18.6 %7013
Test Date:2025-05-22 05:44:20Functions:35.7 %145
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by function hit count
Kernel._fallback0
Kernel._processUserOp0
Kernel._verifyInstallSignature0
Kernel.executeUserOp0
Kernel.fallback0
Kernel.isValidSignature0
Kernel.onlyEntryPointOrSelf0
Kernel.setRoot0
Kernel.validateUserOp0
Kernel.executeFromExecutor3
Kernel.execute9
Kernel._domainNameAndVersion14
Kernel.constructor14
Kernel.installModule15
+
+
+ + + +
Generated by: LCOV version 2.1-1
+
+ + + diff --git a/coverage/src/Kernel.sol.func.html b/coverage/src/Kernel.sol.func.html new file mode 100644 index 00000000..73aa92e9 --- /dev/null +++ b/coverage/src/Kernel.sol.func.html @@ -0,0 +1,173 @@ + + + + + + + LCOV - lcov.info - src/Kernel.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - src - Kernel.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:18.6 %7013
Test Date:2025-05-22 05:44:20Functions:35.7 %145
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by function hit count
Kernel._domainNameAndVersion14
Kernel._fallback0
Kernel._processUserOp0
Kernel._verifyInstallSignature0
Kernel.constructor14
Kernel.execute9
Kernel.executeFromExecutor3
Kernel.executeUserOp0
Kernel.fallback0
Kernel.installModule15
Kernel.isValidSignature0
Kernel.onlyEntryPointOrSelf0
Kernel.setRoot0
Kernel.validateUserOp0
+
+
+ + + +
Generated by: LCOV version 2.1-1
+
+ + + diff --git a/coverage/src/Kernel.sol.gcov.html b/coverage/src/Kernel.sol.gcov.html new file mode 100644 index 00000000..1f0e6756 --- /dev/null +++ b/coverage/src/Kernel.sol.gcov.html @@ -0,0 +1,254 @@ + + + + + + + LCOV - lcov.info - src/Kernel.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - src - Kernel.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:18.6 %7013
Test Date:2025-05-22 05:44:20Functions:35.7 %145
+
+ + + + + + + + +

+
            Line data    Source code
+
+       1              : pragma solidity ^0.8.0;
+       2              : 
+       3              : import {IEntryPoint} from "account-abstraction/interfaces/IEntryPoint.sol";
+       4              : import {IAccount} from "account-abstraction/interfaces/IAccount.sol";
+       5              : import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol";
+       6              : import {IValidator} from "./interfaces/IERC7579Modules.sol";
+       7              : import "./types/Types.sol";
+       8              : import {ModuleManager, Install} from "./core/ModuleManager.sol";
+       9              : import {ExecutionManager} from "./core/ExecutionManager.sol";
+      10              : import {EIP712} from "solady/utils/EIP712.sol";
+      11              : import {Lib4337} from "./Lib4337.sol";
+      12              : import "./types/Error.sol";
+      13              : import "./types/Events.sol";
+      14              : 
+      15              : contract Kernel is ModuleManager, ExecutionManager, EIP712 {
+      16              :     IEntryPoint immutable entryPoint;
+      17              : 
+      18              :     error Unauthorized();
+      19              : 
+      20            0 :     modifier onlyEntryPointOrSelf() {
+      21            0 :         require(msg.sender == address(entryPoint) || msg.sender == address(this), Unauthorized());
+      22              :         _;
+      23              :     }
+      24              : 
+      25           14 :     constructor(IEntryPoint _entryPoint) {
+      26           14 :         entryPoint = _entryPoint;
+      27              :     }
+      28              : 
+      29           14 :     function _domainNameAndVersion() internal pure override returns (string memory name, string memory version) {
+      30           14 :         name = "Kernel";
+      31           14 :         version = "0.4.0";
+      32              :     }
+      33              : 
+      34              :     /// authentication
+      35              :     struct EnableModeSignature {
+      36              :         Install[] packages;
+      37              :         bytes enableSignature;
+      38              :         bytes userOpSignature;
+      39              :     }
+      40              : 
+      41            0 :     function validateUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash, uint256 missingAccountFunds)
+      42              :         external
+      43              :         payable
+      44              :         onlyEntryPointOrSelf
+      45              :         returns (uint256 validationData)
+      46              :     {
+      47            0 :         (ValidationId verifier, bytes32 opHash, bytes calldata userOpSignature) = _processUserOp(userOp, userOpHash);
+      48            0 :         validationData = _validateUserOp(verifier, opHash, userOp, userOpSignature);
+      49              :         assembly {
+      50            0 :             if missingAccountFunds {
+      51            0 :                 pop(call(gas(), caller(), missingAccountFunds, callvalue(), callvalue(), callvalue(), callvalue()))
+      52              :                 //ignore failure (its EntryPoint's job to verify, not account.)
+      53              :             }
+      54              :         }
+      55              :     }
+      56              : 
+      57            0 :     function _processUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash)
+      58              :         internal
+      59              :         returns (ValidationId verifier, bytes32 opHash, bytes calldata signature)
+      60              :     {
+      61              :         /*
+      62              :          userOp.nonce = vMode | vType | vId
+      63              :         */
+      64            0 :         (ValidationMode vMode, ValidationType vType, ValidationId vId) = _parseNonce(userOp.nonce);
+      65            0 :         signature = userOp.signature;
+      66            0 :         if (isEnable(vMode)) {
+      67            0 :             bool enableReplayable = isEnableReplayable(vMode);
+      68            0 :             EnableModeSignature calldata sig;
+      69              :             assembly {
+      70            0 :                 sig := signature.offset
+      71              :             }
+      72            0 :             _verifyInstallSignature(enableReplayable, sig.packages, sig.enableSignature);
+      73            0 :             _install(sig.packages);
+      74            0 :             signature = sig.userOpSignature;
+      75              :         }
+      76            0 :         _checkValidation(vMode, vType, vId);
+      77            0 :         opHash = isReplayable(vMode) ? Lib4337.chainAgnosticUserOpHash(msg.sender, userOp) : userOpHash;
+      78              :     }
+      79              : 
+      80            0 :     function isValidSignature(bytes32 hash, bytes calldata signature) external view returns (bytes4) {}
+      81              : 
+      82              :     /// execution
+      83            0 :     function executeUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash) external payable onlyEntryPointOrSelf {
+      84            0 :         (bool success, bytes memory ret) = address(this).delegatecall(userOp.callData[4:]);
+      85              :     }
+      86              : 
+      87            9 :     function execute(bytes32 mode, bytes calldata executionData) external payable onlyEntryPointOrSelf {
+      88            9 :         _execute(mode, executionData);
+      89              :     }
+      90              : 
+      91            3 :     function executeFromExecutor(bytes32 mode, bytes calldata executionData) external payable onlyExecutor {
+      92            3 :         _execute(mode, executionData);
+      93              :     }
+      94              :     
+      95            0 :     function _fallback() internal {
+      96            0 :         bytes4 selector = bytes4(msg.data);
+      97            0 :         SelectorConfig storage $ = _selectorConfig(selector);
+      98            0 :         if($.target == address(0)) {
+      99            0 :             revert InvalidSelector();
+     100              :         }
+     101            0 :         bytes memory hookData;
+     102            0 :         if(address($.hook) != address(0)) {
+     103            0 :             hookData = _preHook($.hook);
+     104              :         }
+     105              : 
+     106            0 :         bool success;
+     107            0 :         if($.callType == CallType.wrap(bytes1(0x00))) {
+     108            0 :             success = _call($.target, 0, msg.data);
+     109            0 :         } else if($.callType == CallType.wrap(bytes1(0xff))) {
+     110            0 :             success = _delegateCall($.target, msg.data);
+     111              :         }
+     112            0 :         if(!success) {
+     113            0 :             _onRevertThrow();
+     114              :         }
+     115            0 :         if(address($.hook) != address(0)) {
+     116            0 :             _postHook($.hook, hookData);
+     117              :         }
+     118              :     }
+     119              : 
+     120              :     /// management
+     121              :     struct InstallModuleDataFormat {
+     122              :         bytes installData;
+     123              :         bytes internalData;
+     124              :     }
+     125              : 
+     126           15 :     function installModule(uint256 moduleType, address module, bytes calldata initData) external payable onlyEntryPointOrSelf {
+     127           15 :         InstallModuleDataFormat calldata imdf;
+     128              :         assembly {
+     129           15 :             imdf := initData.offset
+     130              :         }
+     131           15 :         _installModule(moduleType, module, imdf.installData, imdf.internalData);
+     132              :     }
+     133              : 
+     134            0 :     function setRoot(ValidationId vId) external payable onlyEntryPointOrSelf {
+     135            0 :         _setRoot(vId);
+     136              :     }
+     137              : 
+     138              :     // NOTE : this ONLY allows root signature, for now
+     139            0 :     function installModule(bool replayable, Install[] calldata packages, bytes calldata signature) external {
+     140            0 :         if(_initialized()) {
+     141              :             // if 7702 or already initialized, use root signature to install module
+     142            0 :             require(_verifyInstallSignature(replayable, packages, signature), InstallSignatureVerificationFailed());
+     143            0 :             _install(packages);
+     144              :         } else {
+     145              :             // this is initialize
+     146              :             // require first package to be the root validator
+     147            0 :             require(packages.length > 0);
+     148            0 :             Install calldata root = packages[0];
+     149            0 :             _install(packages);
+     150            0 :             _setRoot(root);
+     151              :         }
+     152              :     }
+     153              : 
+     154            0 :     function _verifyInstallSignature(bool replayable, Install[] calldata packages, bytes calldata signature)
+     155              :         internal
+     156              :         view
+     157              :         returns (bool success)
+     158              :     {
+     159            0 :         ValidationId vId = _validationStorage().root;
+     160            0 :         function(bytes32) internal view returns(bytes32) hashTypedData =
+     161            0 :             replayable ? _hashTypedDataSansChainId : _hashTypedData;
+     162            0 :         bytes32 digest = hashTypedData(
+     163              :             keccak256(
+     164              :                 abi.encode(
+     165              :                     keccak256(
+     166              :                         "InstallPackages(Install[] packages)Install(uint256 moduleType,address module,bytes moduleData,bytes internalData)"
+     167              :                     ),
+     168              :                     _installHash(packages)
+     169              :                 )
+     170              :             )
+     171              :         );
+     172            0 :         _verifySignature(vId, address(this), digest, signature);
+     173              :     }
+     174              : 
+     175            0 :     fallback() external payable {
+     176            0 :         _fallback();
+     177              :     }
+     178              : }
+        
+
+
+ + + + +
Generated by: LCOV version 2.1-1
+
+ + + diff --git a/coverage/src/KernelFactory.sol.func-c.html b/coverage/src/KernelFactory.sol.func-c.html new file mode 100644 index 00000000..7faeb791 --- /dev/null +++ b/coverage/src/KernelFactory.sol.func-c.html @@ -0,0 +1,96 @@ + + + + + + + LCOV - lcov.info - src/KernelFactory.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - src - KernelFactory.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:50.0 %126
Test Date:2025-05-22 05:44:20Functions:66.7 %32
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by function hit count
KernelFactory.deployWithAdditionalPackage0
KernelFactory.constructor14
KernelFactory.deploy15
+
+
+ + + +
Generated by: LCOV version 2.1-1
+
+ + + diff --git a/coverage/src/KernelFactory.sol.func.html b/coverage/src/KernelFactory.sol.func.html new file mode 100644 index 00000000..1ea9a2cb --- /dev/null +++ b/coverage/src/KernelFactory.sol.func.html @@ -0,0 +1,96 @@ + + + + + + + LCOV - lcov.info - src/KernelFactory.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - src - KernelFactory.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:50.0 %126
Test Date:2025-05-22 05:44:20Functions:66.7 %32
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by function hit count
KernelFactory.constructor14
KernelFactory.deploy15
KernelFactory.deployWithAdditionalPackage0
+
+
+ + + +
Generated by: LCOV version 2.1-1
+
+ + + diff --git a/coverage/src/KernelFactory.sol.gcov.html b/coverage/src/KernelFactory.sol.gcov.html new file mode 100644 index 00000000..b7f3261b --- /dev/null +++ b/coverage/src/KernelFactory.sol.gcov.html @@ -0,0 +1,104 @@ + + + + + + + LCOV - lcov.info - src/KernelFactory.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - src - KernelFactory.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:50.0 %126
Test Date:2025-05-22 05:44:20Functions:66.7 %32
+
+ + + + + + + + +

+
            Line data    Source code
+
+       1              : pragma solidity ^0.8.0;
+       2              : 
+       3              : import {Kernel, Install} from "./Kernel.sol";
+       4              : import {LibClone} from "solady/utils/LibClone.sol";
+       5              : import {IEntryPoint} from "account-abstraction/interfaces/IEntryPoint.sol";
+       6              : 
+       7              : contract KernelFactory {
+       8              :     Kernel public immutable template;
+       9              : 
+      10           14 :     constructor(IEntryPoint _entryPoint) {
+      11           14 :         template = new Kernel(_entryPoint);
+      12              :     }
+      13              : 
+      14           15 :     function deploy(bytes calldata initData) external payable returns (Kernel) {
+      15           15 :         bytes32 salt = keccak256(initData);
+      16           15 :         (bool deployed, address account) = LibClone.createDeterministicERC1967(msg.value, address(template), salt);
+      17           15 :         return Kernel(payable(account));
+      18              :     }
+      19              : 
+      20            0 :     function deployWithAdditionalPackage(bytes calldata initData, bool replayable, Install[] calldata packages, bytes calldata signature) external payable returns (Kernel) {
+      21            0 :         bytes32 salt = keccak256(initData);
+      22            0 :         (bool deployed, address account) = LibClone.createDeterministicERC1967(msg.value, address(template), salt);
+      23              : 
+      24            0 :         Kernel k = Kernel(payable(account));
+      25            0 :         k.installModule(replayable, packages, signature);
+      26            0 :         return k;
+      27              :     }
+      28              : }
+        
+
+
+ + + + +
Generated by: LCOV version 2.1-1
+
+ + + diff --git a/coverage/src/Lib4337.sol.func-c.html b/coverage/src/Lib4337.sol.func-c.html new file mode 100644 index 00000000..add91332 --- /dev/null +++ b/coverage/src/Lib4337.sol.func-c.html @@ -0,0 +1,89 @@ + + + + + + + LCOV - lcov.info - src/Lib4337.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - src - Lib4337.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:0.0 %170
Test Date:2025-05-22 05:44:20Functions:0.0 %20
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by function hit count
Lib4337._hashTypedDataSansChainId0
Lib4337.chainAgnosticUserOpHash0
+
+
+ + + +
Generated by: LCOV version 2.1-1
+
+ + + diff --git a/coverage/src/Lib4337.sol.func.html b/coverage/src/Lib4337.sol.func.html new file mode 100644 index 00000000..2152f584 --- /dev/null +++ b/coverage/src/Lib4337.sol.func.html @@ -0,0 +1,89 @@ + + + + + + + LCOV - lcov.info - src/Lib4337.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - src - Lib4337.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:0.0 %170
Test Date:2025-05-22 05:44:20Functions:0.0 %20
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by function hit count
Lib4337._hashTypedDataSansChainId0
Lib4337.chainAgnosticUserOpHash0
+
+
+ + + +
Generated by: LCOV version 2.1-1
+
+ + + diff --git a/coverage/src/Lib4337.sol.gcov.html b/coverage/src/Lib4337.sol.gcov.html new file mode 100644 index 00000000..cde3e4fb --- /dev/null +++ b/coverage/src/Lib4337.sol.gcov.html @@ -0,0 +1,130 @@ + + + + + + + LCOV - lcov.info - src/Lib4337.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - src - Lib4337.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:0.0 %170
Test Date:2025-05-22 05:44:20Functions:0.0 %20
+
+ + + + + + + + +

+
            Line data    Source code
+
+       1              : pragma solidity ^0.8.0;
+       2              : 
+       3              : import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol";
+       4              : import {UserOperationLib} from "account-abstraction/core/UserOperationLib.sol";
+       5              : import {Eip7702Support} from "account-abstraction/core/Eip7702Support.sol";
+       6              : interface IERC5267 {
+       7              :     function eip712Domain()
+       8              :         external
+       9              :         view
+      10              :         returns (
+      11              :             bytes1 fields,
+      12              :             string memory name,
+      13              :             string memory version,
+      14              :             uint256 chainId,
+      15              :             address verifyingContract,
+      16              :             bytes32 salt,
+      17              :             uint256[] memory extensions
+      18              :         );
+      19              : }
+      20              : 
+      21              : library Lib4337 {
+      22              :     bytes32 internal constant _DOMAIN_TYPEHASH_SANS_CHAIN_ID =
+      23              :         0x91ab3d17e3a50a9d89e63fd30b92be7f5336b03b287bb946787a83a9d62a2766;
+      24            0 :     function chainAgnosticUserOpHash(address ep, PackedUserOperation calldata userOp) public view returns(bytes32) {
+      25            0 :         bytes32 overrideInitCodeHash = Eip7702Support._getEip7702InitCodeHashOverride(userOp);
+      26            0 :         return
+      27            0 :             _hashTypedDataSansChainId(ep, UserOperationLib.hash(userOp, overrideInitCodeHash));
+      28              :     }
+      29              :     
+      30              :     /// @dev Variant of `_hashTypedData` that excludes the chain ID.
+      31              :     /// Included for the niche use case of cross-chain workflows.
+      32            0 :     function _hashTypedDataSansChainId(address addr, bytes32 structHash)
+      33              :         internal
+      34              :         view
+      35              :         returns (bytes32 digest)
+      36              :     {
+      37            0 :         (,string memory name, string memory version, , , , ) = IERC5267(addr).eip712Domain();
+      38              :         /// @solidity memory-safe-assembly
+      39              :         assembly {
+      40            0 :             let m := mload(0x40) // Load the free memory pointer.
+      41            0 :             mstore(0x00, _DOMAIN_TYPEHASH_SANS_CHAIN_ID)
+      42            0 :             mstore(0x20, keccak256(add(name, 0x20), mload(name)))
+      43            0 :             mstore(0x40, keccak256(add(version, 0x20), mload(version)))
+      44            0 :             mstore(0x60, addr)
+      45              :             // Compute the digest.
+      46            0 :             mstore(0x20, keccak256(0x00, 0x80)) // Store the domain separator.
+      47            0 :             mstore(0x00, 0x1901) // Store "\x19\x01".
+      48            0 :             mstore(0x40, structHash) // Store the struct hash.
+      49            0 :             digest := keccak256(0x1e, 0x42)
+      50            0 :             mstore(0x40, m) // Restore the free memory pointer.
+      51            0 :             mstore(0x60, 0) // Restore the zero pointer.
+      52              :         }
+      53              :     }
+      54              : }
+        
+
+
+ + + + +
Generated by: LCOV version 2.1-1
+
+ + + diff --git a/coverage/src/core/ExecutionManager.sol.func-c.html b/coverage/src/core/ExecutionManager.sol.func-c.html new file mode 100644 index 00000000..cf5c05ac --- /dev/null +++ b/coverage/src/core/ExecutionManager.sol.func-c.html @@ -0,0 +1,131 @@ + + + + + + + LCOV - lcov.info - src/core/ExecutionManager.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - src/core - ExecutionManager.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:95.9 %4947
Test Date:2025-05-22 05:44:20Functions:100.0 %88
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by function hit count
ExecutionManager._onRevertSilent3
ExecutionManager._onRevertThrow3
ExecutionManager._delegateCall4
ExecutionManager._executeBatchCall4
ExecutionManager._executeCall4
ExecutionManager._executeDelegateCall4
ExecutionManager._call12
ExecutionManager._execute12
+
+
+ + + +
Generated by: LCOV version 2.1-1
+
+ + + diff --git a/coverage/src/core/ExecutionManager.sol.func.html b/coverage/src/core/ExecutionManager.sol.func.html new file mode 100644 index 00000000..6f09280e --- /dev/null +++ b/coverage/src/core/ExecutionManager.sol.func.html @@ -0,0 +1,131 @@ + + + + + + + LCOV - lcov.info - src/core/ExecutionManager.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - src/core - ExecutionManager.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:95.9 %4947
Test Date:2025-05-22 05:44:20Functions:100.0 %88
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by function hit count
ExecutionManager._call12
ExecutionManager._delegateCall4
ExecutionManager._execute12
ExecutionManager._executeBatchCall4
ExecutionManager._executeCall4
ExecutionManager._executeDelegateCall4
ExecutionManager._onRevertSilent3
ExecutionManager._onRevertThrow3
+
+
+ + + +
Generated by: LCOV version 2.1-1
+
+ + + diff --git a/coverage/src/core/ExecutionManager.sol.gcov.html b/coverage/src/core/ExecutionManager.sol.gcov.html new file mode 100644 index 00000000..6119648e --- /dev/null +++ b/coverage/src/core/ExecutionManager.sol.gcov.html @@ -0,0 +1,168 @@ + + + + + + + LCOV - lcov.info - src/core/ExecutionManager.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - src/core - ExecutionManager.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:95.9 %4947
Test Date:2025-05-22 05:44:20Functions:100.0 %88
+
+ + + + + + + + +

+
            Line data    Source code
+
+       1              : pragma solidity ^0.8.0;
+       2              : 
+       3              : import {LibERC7579} from "solady/accounts/LibERC7579.sol";
+       4              : import "../types/Error.sol";
+       5              : 
+       6              : abstract contract ExecutionManager {
+       7           12 :     function _execute(bytes32 mode, bytes calldata executionData) internal {
+       8           12 :         bytes1 callType = LibERC7579.getCallType(mode);
+       9           12 :         bytes1 execType = LibERC7579.getExecType(mode);
+      10           12 :         function() onRevert;
+      11           12 :         if(execType == LibERC7579.EXECTYPE_DEFAULT) {
+      12            9 :             onRevert = _onRevertThrow;
+      13            3 :         } else if(execType == LibERC7579.EXECTYPE_TRY) {
+      14            3 :             onRevert = _onRevertSilent;
+      15              :         } else {
+      16            0 :             revert NotSupportedExecType();
+      17              :         }
+      18              : 
+      19           12 :         function(bytes calldata, function()) executeFunction;
+      20           12 :         if(callType == LibERC7579.CALLTYPE_SINGLE) {
+      21            4 :             executeFunction = _executeCall;
+      22            8 :         } else if(callType == LibERC7579.CALLTYPE_BATCH) {
+      23            4 :             executeFunction = _executeBatchCall;
+      24            4 :         } else if(callType == LibERC7579.CALLTYPE_DELEGATECALL) {
+      25            4 :             executeFunction = _executeDelegateCall;
+      26              :         } else {
+      27            0 :             revert NotSupportedCallType();
+      28              :         }
+      29           12 :         executeFunction(executionData, onRevert);
+      30              :     }
+      31              : 
+      32            4 :     function _executeCall(bytes calldata executionData, function() onRevert) internal {
+      33            4 :         (address target, uint256 value, bytes calldata data) = LibERC7579.decodeSingle(executionData);
+      34            4 :         bool success = _call(target, value, data);
+      35            4 :         if(!success) {
+      36            2 :             onRevert();
+      37              :         }
+      38              :     }
+      39              : 
+      40            4 :     function _executeDelegateCall(bytes calldata executionData, function() onRevert) internal {
+      41            4 :         (address delegate, bytes calldata data) = LibERC7579.decodeDelegate(executionData);
+      42            4 :         bool success = _delegateCall(delegate, data);
+      43            4 :         if(!success) {
+      44            2 :             onRevert();
+      45              :         }
+      46              :     }
+      47              : 
+      48            4 :     function _executeBatchCall(bytes calldata executionData, function() onRevert) internal {
+      49            4 :         bytes32[] calldata pointers = LibERC7579.decodeBatch(executionData);
+      50            4 :         uint256 length = pointers.length;
+      51            4 :         bytes[] memory result = new bytes[](length);
+      52              :         unchecked {
+      53            4 :             for (uint256 i; i < length; i++) {
+      54            8 :                 (address target, uint256 value, bytes calldata data) = LibERC7579.getExecution(pointers, i);
+      55            8 :                 bool success = _call(target, value, data);
+      56            8 :                 if(!success) {
+      57            2 :                     onRevert();
+      58              :                 }
+      59              :             }
+      60              :         }
+      61              :     }
+      62              : 
+      63            3 :     function _onRevertThrow() internal {
+      64              :         assembly {
+      65              :             // Bubble up the revert if the call reverts.
+      66            3 :             returndatacopy(0x00, 0x00, returndatasize())
+      67            3 :             revert(0x00, returndatasize())
+      68              :         }
+      69              :     }
+      70              : 
+      71            3 :     function _onRevertSilent() internal {
+      72              :     }
+      73              : 
+      74           12 :     function _call(address target, uint256 value, bytes calldata callData) internal returns(bool success){
+      75              :         /// @solidity memory-safe-assembly
+      76              :         assembly {
+      77           12 :             let ptr := mload(0x40)
+      78           12 :             calldatacopy(ptr, callData.offset, callData.length)
+      79           12 :             success := call(gas(), target, value, ptr, callData.length, codesize(), 0x00)
+      80              :         }
+      81              :     }
+      82              : 
+      83            4 :     function _delegateCall(address delegate, bytes calldata callData) internal returns(bool success){
+      84              :         /// @solidity memory-safe-assembly
+      85              :         assembly {
+      86            4 :             let ptr := mload(0x40)
+      87            4 :             calldatacopy(ptr, callData.offset, callData.length)
+      88              :             // Forwards the `data` to `delegate` via delegatecall.
+      89            4 :             success := delegatecall(gas(), delegate, ptr, callData.length, codesize(), 0x00)
+      90              :         }
+      91              :     }
+      92              : }
+        
+
+
+ + + + +
Generated by: LCOV version 2.1-1
+
+ + + diff --git a/coverage/src/core/ExecutorManager.sol.func-c.html b/coverage/src/core/ExecutorManager.sol.func-c.html new file mode 100644 index 00000000..96e08063 --- /dev/null +++ b/coverage/src/core/ExecutorManager.sol.func-c.html @@ -0,0 +1,110 @@ + + + + + + + LCOV - lcov.info - src/core/ExecutorManager.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - src/core - ExecutorManager.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:69.2 %139
Test Date:2025-05-22 05:44:20Functions:60.0 %53
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by function hit count
ExecutorManager._uninstallExecutor0
ExecutorManager.executorConfig0
ExecutorManager._installExecutor14
ExecutorManager._executorConfig17
ExecutorManager._executorStorage17
+
+
+ + + +
Generated by: LCOV version 2.1-1
+
+ + + diff --git a/coverage/src/core/ExecutorManager.sol.func.html b/coverage/src/core/ExecutorManager.sol.func.html new file mode 100644 index 00000000..92617d23 --- /dev/null +++ b/coverage/src/core/ExecutorManager.sol.func.html @@ -0,0 +1,110 @@ + + + + + + + LCOV - lcov.info - src/core/ExecutorManager.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - src/core - ExecutorManager.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:69.2 %139
Test Date:2025-05-22 05:44:20Functions:60.0 %53
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by function hit count
ExecutorManager._executorConfig17
ExecutorManager._executorStorage17
ExecutorManager._installExecutor14
ExecutorManager._uninstallExecutor0
ExecutorManager.executorConfig0
+
+
+ + + +
Generated by: LCOV version 2.1-1
+
+ + + diff --git a/coverage/src/core/ExecutorManager.sol.gcov.html b/coverage/src/core/ExecutorManager.sol.gcov.html new file mode 100644 index 00000000..4ef72290 --- /dev/null +++ b/coverage/src/core/ExecutorManager.sol.gcov.html @@ -0,0 +1,119 @@ + + + + + + + LCOV - lcov.info - src/core/ExecutorManager.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - src/core - ExecutorManager.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:69.2 %139
Test Date:2025-05-22 05:44:20Functions:60.0 %53
+
+ + + + + + + + +

+
            Line data    Source code
+
+       1              : pragma solidity ^0.8.0;
+       2              : 
+       3              : import "../types/Types.sol";
+       4              : import "../types/Constants.sol";
+       5              : import "../interfaces/IERC7579Modules.sol";
+       6              : 
+       7              : contract ExecutorManager {
+       8              :     error NotExecutor();
+       9              :     struct ExecutorConfig {
+      10              :         IHook hook; // address(1) : hook not required, address(0) : validator not installed
+      11              :     }
+      12              : 
+      13              :     struct ExecutorStorage {
+      14              :         mapping(IExecutor => ExecutorConfig) executorConfig;
+      15              :     }
+      16              : 
+      17           17 :     function _executorStorage() internal view returns (ExecutorStorage storage $) {
+      18              :         assembly {
+      19           17 :             $.slot := EXECUTOR_MANAGER_STORAGE_SLOT
+      20              :         }
+      21              :     }
+      22              : 
+      23            0 :     function executorConfig(IExecutor executor) external view returns (ExecutorConfig memory) {
+      24            0 :         return _executorConfig(executor);
+      25              :     }
+      26              : 
+      27           17 :     function _executorConfig(IExecutor executor) internal view returns (ExecutorConfig storage config) {
+      28           17 :         config = _executorStorage().executorConfig[executor];
+      29              :     }
+      30              : 
+      31           14 :     function _installExecutor(address _executor, bytes calldata _internalData, bool _installSuccess) internal {
+      32              :         // NOTE: we don't care if install was successful 
+      33           14 :         address hook = _internalData.length >= 20 ? address(bytes20(_internalData[0:20])) : address(0);
+      34           14 :         if(hook == address(0)) {
+      35           14 :             hook = address(1); // address(1) indicates it is installed and does not require any hook
+      36              :         }
+      37           14 :         _executorConfig(IExecutor(_executor)).hook = IHook(hook);
+      38              :     }
+      39              : 
+      40            0 :     function _uninstallExecutor(address _executor, bytes calldata _internalData, bool _installSuccess) internal {
+      41            0 :         _executorConfig(IExecutor(_executor)).hook = IHook(address(0));
+      42              :     }
+      43              : }
+        
+
+
+ + + + +
Generated by: LCOV version 2.1-1
+
+ + + diff --git a/coverage/src/core/HookManager.sol.func-c.html b/coverage/src/core/HookManager.sol.func-c.html new file mode 100644 index 00000000..7f44cd61 --- /dev/null +++ b/coverage/src/core/HookManager.sol.func-c.html @@ -0,0 +1,103 @@ + + + + + + + LCOV - lcov.info - src/core/HookManager.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - src/core - HookManager.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:45.5 %115
Test Date:2025-05-22 05:44:20Functions:50.0 %42
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by function hit count
HookManager._installHook0
HookManager._uninstallHook0
HookManager._postHook3
HookManager._preHook3
+
+
+ + + +
Generated by: LCOV version 2.1-1
+
+ + + diff --git a/coverage/src/core/HookManager.sol.func.html b/coverage/src/core/HookManager.sol.func.html new file mode 100644 index 00000000..f7d8c7a7 --- /dev/null +++ b/coverage/src/core/HookManager.sol.func.html @@ -0,0 +1,103 @@ + + + + + + + LCOV - lcov.info - src/core/HookManager.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - src/core - HookManager.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:45.5 %115
Test Date:2025-05-22 05:44:20Functions:50.0 %42
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by function hit count
HookManager._installHook0
HookManager._postHook3
HookManager._preHook3
HookManager._uninstallHook0
+
+
+ + + +
Generated by: LCOV version 2.1-1
+
+ + + diff --git a/coverage/src/core/HookManager.sol.gcov.html b/coverage/src/core/HookManager.sol.gcov.html new file mode 100644 index 00000000..b32210cd --- /dev/null +++ b/coverage/src/core/HookManager.sol.gcov.html @@ -0,0 +1,113 @@ + + + + + + + LCOV - lcov.info - src/core/HookManager.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - src/core - HookManager.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:45.5 %115
Test Date:2025-05-22 05:44:20Functions:50.0 %42
+
+ + + + + + + + +

+
            Line data    Source code
+
+       1              : pragma solidity ^0.8.0;
+       2              : 
+       3              : import {IHook, IFallback, IModule} from "../interfaces/IERC7579Modules.sol";
+       4              : import {CallType} from "../types/Types.sol";
+       5              : import {
+       6              :     SELECTOR_MANAGER_STORAGE_SLOT,
+       7              :     CALLTYPE_DELEGATECALL,
+       8              :     CALLTYPE_SINGLE,
+       9              :     MODULE_TYPE_FALLBACK
+      10              : } from "../types/Constants.sol";
+      11              : import "../types/Error.sol";
+      12              : 
+      13              : abstract contract HookManager {
+      14            0 :     function _installHook(address _hook, bytes calldata _internalData, bool _installSuccess) internal {
+      15            0 :         if(_internalData.length == 0) {
+      16            0 :             require(_installSuccess, ModuleInstallFailed());
+      17              :         }
+      18              :     }
+      19              : 
+      20            0 :     function _uninstallHook(address _hook, bytes calldata _internalData, bool _uninstallSuccess) internal {
+      21              :         // no-op
+      22              :     }
+      23              : 
+      24            3 :     function _preHook(IHook _hook) internal returns(bytes memory context){
+      25            3 :         require(address(_hook) != address(0), NotInstalled());
+      26            3 :         if(address(_hook) != address(1)) {
+      27            0 :             context = _hook.preCheck(msg.sender, msg.value, msg.data);
+      28              :         }
+      29              :     }
+      30            3 :     function _postHook(IHook _hook, bytes memory context) internal {
+      31              :         // bool success,
+      32              :         // bytes memory result
+      33            3 :         if(address(_hook) != address(1)) {
+      34            0 :             _hook.postCheck(context);
+      35              :         }
+      36              :     }
+      37              : }
+        
+
+
+ + + + +
Generated by: LCOV version 2.1-1
+
+ + + diff --git a/coverage/src/core/ModuleManager.sol.func-c.html b/coverage/src/core/ModuleManager.sol.func-c.html new file mode 100644 index 00000000..2cda5175 --- /dev/null +++ b/coverage/src/core/ModuleManager.sol.func-c.html @@ -0,0 +1,117 @@ + + + + + + + LCOV - lcov.info - src/core/ModuleManager.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - src/core - ModuleManager.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:38.5 %3915
Test Date:2025-05-22 05:44:20Functions:50.0 %63
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by function hit count
ModuleManager._initialized0
ModuleManager._installHash0
ModuleManager._uninstall0
ModuleManager.onlyExecutor3
ModuleManager._install15
ModuleManager._installModule15
+
+
+ + + +
Generated by: LCOV version 2.1-1
+
+ + + diff --git a/coverage/src/core/ModuleManager.sol.func.html b/coverage/src/core/ModuleManager.sol.func.html new file mode 100644 index 00000000..4234851d --- /dev/null +++ b/coverage/src/core/ModuleManager.sol.func.html @@ -0,0 +1,117 @@ + + + + + + + LCOV - lcov.info - src/core/ModuleManager.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - src/core - ModuleManager.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:38.5 %3915
Test Date:2025-05-22 05:44:20Functions:50.0 %63
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by function hit count
ModuleManager._initialized0
ModuleManager._install15
ModuleManager._installHash0
ModuleManager._installModule15
ModuleManager._uninstall0
ModuleManager.onlyExecutor3
+
+
+ + + +
Generated by: LCOV version 2.1-1
+
+ + + diff --git a/coverage/src/core/ModuleManager.sol.gcov.html b/coverage/src/core/ModuleManager.sol.gcov.html new file mode 100644 index 00000000..df5096d6 --- /dev/null +++ b/coverage/src/core/ModuleManager.sol.gcov.html @@ -0,0 +1,173 @@ + + + + + + + LCOV - lcov.info - src/core/ModuleManager.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - src/core - ModuleManager.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:38.5 %3915
Test Date:2025-05-22 05:44:20Functions:50.0 %63
+
+ + + + + + + + +

+
            Line data    Source code
+
+       1              : pragma solidity ^0.8.0;
+       2              : 
+       3              : import "../interfaces/IERC7579Modules.sol";
+       4              : import {ValidationManager} from "./ValidationManager.sol";
+       5              : import {ExecutorManager} from "./ExecutorManager.sol";
+       6              : import {HookManager} from "./HookManager.sol";
+       7              : import {SelectorManager} from "./SelectorManager.sol";
+       8              : import "../types/Error.sol";
+       9              : import "../types/Events.sol";
+      10              : import "../types/Structs.sol";
+      11              : import "../types/Types.sol";
+      12              : 
+      13              : 
+      14              : function calldataKeccak(bytes calldata data) pure returns (bytes32 ret) {
+      15              :     assembly ("memory-safe") {
+      16              :         let mem := mload(0x40)
+      17              :         let len := data.length
+      18              :         calldatacopy(mem, data.offset, len)
+      19              :         ret := keccak256(mem, len)
+      20              :     }
+      21              : }
+      22              : 
+      23              : contract ModuleManager is ValidationManager, ExecutorManager, HookManager, SelectorManager {
+      24            3 :     modifier onlyExecutor {
+      25            3 :         IHook hook = _executorConfig(IExecutor(msg.sender)).hook;
+      26            3 :         bytes memory hookData = _preHook(hook);
+      27              :         _;
+      28            3 :         _postHook(hook, hookData);
+      29              :     }
+      30              : 
+      31            0 :     function _initialized() internal view returns(bool) {
+      32            0 :         return bytes3(address(this).code) == bytes3(0xef0100) || ValidationId.unwrap(_validationStorage().root) != bytes20(0);
+      33              :     }
+      34              : 
+      35            0 :     function _installHash(Install[] calldata packages) internal pure returns (bytes32) {
+      36            0 :         bytes32[] memory packageHashes = new bytes32[](packages.length);
+      37            0 :         for (uint256 i = 0; i < packages.length; i++) {
+      38            0 :             Install calldata pkg = packages[i];
+      39            0 :             packageHashes[i] = keccak256(
+      40              :                 abi.encode(pkg.moduleType, pkg.module, calldataKeccak(pkg.moduleData), calldataKeccak(pkg.internalData))
+      41              :             );
+      42              :         }
+      43            0 :         return keccak256(abi.encodePacked(packageHashes));
+      44              :     }
+      45              : 
+      46           15 :     function _installModule(uint256 moduleType, address module, bytes calldata moduleData, bytes calldata internalData)
+      47              :         internal
+      48              :     {
+      49           15 :         function(address, bytes calldata, bool) hook;
+      50           15 :         if (moduleType == 1) {
+      51            1 :             hook = _installValidator;
+      52           14 :         } else if(moduleType == 2) {
+      53           14 :             hook = _installExecutor;
+      54            0 :         } else if(moduleType == 3) {
+      55            0 :             hook = _installSelector;
+      56            0 :         } else if(moduleType == 4) {
+      57            0 :             hook = _installHook;
+      58            0 :         } else if(moduleType == 5) {
+      59            0 :             hook = _installPolicy;
+      60            0 :         } else if(moduleType == 6) {
+      61            0 :             hook = _installSigner;
+      62              :         } else {
+      63            0 :             revert NotImplemented();
+      64              :         }
+      65           15 :         _install(module, moduleData, internalData, hook);
+      66           15 :         emit ModuleInstalled(moduleType, module);
+      67              :     }
+      68              : 
+      69            0 :     function _install(Install[] calldata packages) internal {
+      70            0 :         for (uint256 i = 0; i < packages.length; i++) {
+      71            0 :             Install calldata pkg = packages[i];
+      72            0 :             _installModule(pkg.moduleType, pkg.module, pkg.moduleData, pkg.internalData);
+      73              :         }
+      74              :     }
+      75              : 
+      76           15 :     function _install(
+      77              :         address module,
+      78              :         bytes calldata data,
+      79              :         bytes calldata internalData,
+      80              :         function(address, bytes calldata, bool) hook
+      81              :     ) internal {
+      82           15 :         (bool success,) = module.call(abi.encodeWithSelector(IModule.onInstall.selector, data));
+      83           15 :         hook(module, internalData, success);
+      84              :     }
+      85              : 
+      86            0 :     function _uninstall(
+      87              :         address module,
+      88              :         bytes calldata data,
+      89              :         bytes calldata internalData,
+      90              :         function(address, bytes calldata, bool) hook
+      91              :     ) internal {
+      92              :         // TODO: make sure we use extra safe call
+      93            0 :         (bool success,) = module.call(abi.encodeWithSelector(IModule.onUninstall.selector, data));
+      94            0 :         hook(module, internalData, success);
+      95              :     }
+      96              : 
+      97              : }
+        
+
+
+ + + + +
Generated by: LCOV version 2.1-1
+
+ + + diff --git a/coverage/src/core/SelectorManager.sol.func-c.html b/coverage/src/core/SelectorManager.sol.func-c.html new file mode 100644 index 00000000..bf293a82 --- /dev/null +++ b/coverage/src/core/SelectorManager.sol.func-c.html @@ -0,0 +1,103 @@ + + + + + + + LCOV - lcov.info - src/core/SelectorManager.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - src/core - SelectorManager.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:0.0 %160
Test Date:2025-05-22 05:44:20Functions:0.0 %40
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by function hit count
SelectorManager._installSelector0
SelectorManager._selectorConfig0
SelectorManager._selectorStorage0
SelectorManager.selectorConfig0
+
+
+ + + +
Generated by: LCOV version 2.1-1
+
+ + + diff --git a/coverage/src/core/SelectorManager.sol.func.html b/coverage/src/core/SelectorManager.sol.func.html new file mode 100644 index 00000000..865911d0 --- /dev/null +++ b/coverage/src/core/SelectorManager.sol.func.html @@ -0,0 +1,103 @@ + + + + + + + LCOV - lcov.info - src/core/SelectorManager.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - src/core - SelectorManager.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:0.0 %160
Test Date:2025-05-22 05:44:20Functions:0.0 %40
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by function hit count
SelectorManager._installSelector0
SelectorManager._selectorConfig0
SelectorManager._selectorStorage0
SelectorManager.selectorConfig0
+
+
+ + + +
Generated by: LCOV version 2.1-1
+
+ + + diff --git a/coverage/src/core/SelectorManager.sol.gcov.html b/coverage/src/core/SelectorManager.sol.gcov.html new file mode 100644 index 00000000..61307ca8 --- /dev/null +++ b/coverage/src/core/SelectorManager.sol.gcov.html @@ -0,0 +1,127 @@ + + + + + + + LCOV - lcov.info - src/core/SelectorManager.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - src/core - SelectorManager.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:0.0 %160
Test Date:2025-05-22 05:44:20Functions:0.0 %40
+
+ + + + + + + + +

+
            Line data    Source code
+
+       1              : // SPDX-License-Identifier: MIT
+       2              : pragma solidity ^0.8.0;
+       3              : 
+       4              : import {IHook, IFallback, IModule} from "../interfaces/IERC7579Modules.sol";
+       5              : import {CallType} from "../types/Types.sol";
+       6              : import {
+       7              :     SELECTOR_MANAGER_STORAGE_SLOT,
+       8              :     CALLTYPE_DELEGATECALL,
+       9              :     CALLTYPE_SINGLE,
+      10              :     MODULE_TYPE_FALLBACK
+      11              : } from "../types/Constants.sol";
+      12              : import "../types/Error.sol";
+      13              : 
+      14              : abstract contract SelectorManager {
+      15              : 
+      16              :     struct SelectorConfig {
+      17              :         IHook hook; // 20 bytes for hook address
+      18              :         address target; // 20 bytes target will be fallback module, called with call
+      19              :         CallType callType;
+      20              :     }
+      21              : 
+      22              :     struct SelectorStorage {
+      23              :         mapping(bytes4 => SelectorConfig) selectorConfig;
+      24              :     }
+      25              : 
+      26            0 :     function selectorConfig(bytes4 selector) external view returns (SelectorConfig memory) {
+      27            0 :         return _selectorConfig(selector);
+      28              :     }
+      29              : 
+      30            0 :     function _selectorConfig(bytes4 selector) internal view returns (SelectorConfig storage config) {
+      31            0 :         config = _selectorStorage().selectorConfig[selector];
+      32              :     }
+      33              : 
+      34            0 :     function _selectorStorage() internal pure returns (SelectorStorage storage ss) {
+      35            0 :         bytes32 slot = SELECTOR_MANAGER_STORAGE_SLOT;
+      36              :         assembly {
+      37            0 :             ss.slot := slot
+      38              :         }
+      39              :     }
+      40              : 
+      41            0 :     function _installSelector(address _module, bytes calldata _internalData, bool _installSuccess) internal {
+      42            0 :         CallType callType = CallType.wrap(bytes1(_internalData[4]));
+      43            0 :         require(callType == CALLTYPE_DELEGATECALL || _installSuccess, ModuleInstallFailed());
+      44            0 :         bytes4 selector = bytes4(_internalData[0:4]);
+      45            0 :         address hook = address(bytes20(_internalData[5:25]));
+      46            0 :         SelectorConfig storage $ = _selectorConfig(selector);
+      47            0 :         $.target = _module;
+      48            0 :         $.callType = callType;
+      49            0 :         $.hook = IHook(hook);
+      50              :     }
+      51              : }
+        
+
+
+ + + + +
Generated by: LCOV version 2.1-1
+
+ + + diff --git a/coverage/src/core/ValidationManager.sol.func-c.html b/coverage/src/core/ValidationManager.sol.func-c.html new file mode 100644 index 00000000..53b4a84f --- /dev/null +++ b/coverage/src/core/ValidationManager.sol.func-c.html @@ -0,0 +1,166 @@ + + + + + + + LCOV - lcov.info - src/core/ValidationManager.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - src/core - ValidationManager.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:9.2 %656
Test Date:2025-05-22 05:44:20Functions:15.4 %132
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by function hit count
ValidationManager._checkValidation0
ValidationManager._installPolicy0
ValidationManager._installSigner0
ValidationManager._parseNonce0
ValidationManager._setRoot0
ValidationManager._uninstallPolicy0
ValidationManager._uninstallSigner0
ValidationManager._uninstallValidator0
ValidationManager._validateUserOp0
ValidationManager._verify7702Signature0
ValidationManager._verifySignature0
ValidationManager._installValidator1
ValidationManager._validationStorage1
+
+
+ + + +
Generated by: LCOV version 2.1-1
+
+ + + diff --git a/coverage/src/core/ValidationManager.sol.func.html b/coverage/src/core/ValidationManager.sol.func.html new file mode 100644 index 00000000..a5b52db3 --- /dev/null +++ b/coverage/src/core/ValidationManager.sol.func.html @@ -0,0 +1,166 @@ + + + + + + + LCOV - lcov.info - src/core/ValidationManager.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - src/core - ValidationManager.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:9.2 %656
Test Date:2025-05-22 05:44:20Functions:15.4 %132
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by function hit count
ValidationManager._checkValidation0
ValidationManager._installPolicy0
ValidationManager._installSigner0
ValidationManager._installValidator1
ValidationManager._parseNonce0
ValidationManager._setRoot0
ValidationManager._uninstallPolicy0
ValidationManager._uninstallSigner0
ValidationManager._uninstallValidator0
ValidationManager._validateUserOp0
ValidationManager._validationStorage1
ValidationManager._verify7702Signature0
ValidationManager._verifySignature0
+
+
+ + + +
Generated by: LCOV version 2.1-1
+
+ + + diff --git a/coverage/src/core/ValidationManager.sol.gcov.html b/coverage/src/core/ValidationManager.sol.gcov.html new file mode 100644 index 00000000..2a13e66f --- /dev/null +++ b/coverage/src/core/ValidationManager.sol.gcov.html @@ -0,0 +1,240 @@ + + + + + + + LCOV - lcov.info - src/core/ValidationManager.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - src/core - ValidationManager.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:9.2 %656
Test Date:2025-05-22 05:44:20Functions:15.4 %132
+
+ + + + + + + + +

+
            Line data    Source code
+
+       1              : pragma solidity ^0.8.0;
+       2              : 
+       3              : import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol";
+       4              : import "../interfaces/IERC7579Modules.sol";
+       5              : import "../types/Error.sol";
+       6              : import "../types/Types.sol";
+       7              : import "../types/Constants.sol";
+       8              : import "../types/Structs.sol";
+       9              : import {ECDSA} from "solady/utils/ECDSA.sol";
+      10              : 
+      11              : struct ValidationInfo {
+      12              :     ValidationType vType;
+      13              :     address[] policies;
+      14              :     address signer;
+      15              :     bytes4 group;
+      16              : }
+      17              : 
+      18              : struct ValidationGroupInfo {
+      19              :     mapping(bytes4 selector => bool) allowed;
+      20              :     bytes32 permission;
+      21              : }
+      22              : 
+      23              : struct ValidationStorage {
+      24              :     ValidationId root;
+      25              :     mapping(ValidationId vId => ValidationInfo) vInfo;
+      26              :     mapping(bytes4 group => ValidationGroupInfo) gInfo;
+      27              : }
+      28              : 
+      29              : function getValidator(ValidationId vId) pure returns (address v) {
+      30              :     assembly {
+      31              :         v := shr(96, vId)
+      32              :     }
+      33              : }
+      34              : 
+      35              : function getType(ValidationId validator) pure returns (ValidationType vType) {
+      36              :     assembly {
+      37              :         vType := validator
+      38              :     }
+      39              : }
+      40              : 
+      41              : abstract contract ValidationManager {
+      42              :     ValidationId transient installingPermission;
+      43              : 
+      44            1 :     function _validationStorage() internal view returns (ValidationStorage storage $) {
+      45              :         assembly {
+      46            1 :             $.slot := VALIDATION_MANAGER_STORAGE_SLOT
+      47              :         }
+      48              :     }
+      49              : 
+      50            1 :     function _installValidator(address _validator, bytes calldata _internalData, bool _installSuccess) internal {
+      51            1 :         require(_installSuccess, ModuleInstallFailed());
+      52            1 :         ValidationStorage storage $ = _validationStorage();
+      53            1 :         $.vInfo[ValidationId.wrap(bytes20(_validator))].vType = VALIDATION_TYPE_VALIDATOR;
+      54              :     }
+      55              : 
+      56            0 :     function _uninstallValidator(address _validator, bytes calldata _internalData, bool _uninstallSuccess)
+      57              :         internal
+      58              :     {
+      59            0 :         ValidationStorage storage $ = _validationStorage();
+      60            0 :         $.vInfo[ValidationId.wrap(bytes20(_validator))].vType = VALIDATION_TYPE_VALIDATOR;
+      61              :     }
+      62              : 
+      63            0 :     function _installPolicy(address _policy, bytes calldata _internalData, bool _installSuccess) internal {
+      64            0 :         require(_installSuccess, ModuleInstallFailed());
+      65            0 :         ValidationStorage storage $ = _validationStorage();
+      66            0 :         ValidationId vId = ValidationId.wrap(bytes20(_internalData[0:20]));
+      67            0 :         if(installingPermission == ValidationId.wrap(bytes20(0))) {
+      68            0 :             require(vId != ValidationId.wrap(bytes20(0)), "invalid validationId");
+      69            0 :             installingPermission = ValidationId.wrap(bytes20(_internalData[0:20]));
+      70            0 :             $.vInfo[vId].vType = VALIDATION_TYPE_PERMISSION;
+      71              :         } else {
+      72            0 :             require(installingPermission == vId, "permissionId should be consistent");
+      73              :         }
+      74            0 :         $.vInfo[vId].policies.push(_policy);
+      75              :     }
+      76              : 
+      77            0 :     function _uninstallPolicy(address _policy, bytes calldata _internalData, bool _uninstallSuccess) internal {
+      78              :     }
+      79              : 
+      80            0 :     function _installSigner(address _signer, bytes calldata _internalData, bool _installSuccess) internal {
+      81            0 :         require(_installSuccess, ModuleInstallFailed());
+      82            0 :         ValidationStorage storage $ = _validationStorage();
+      83            0 :         ValidationId vId = ValidationId.wrap(bytes20(_internalData[0:20]));
+      84            0 :         if(installingPermission == ValidationId.wrap(bytes20(0))) {
+      85            0 :             require(vId != ValidationId.wrap(bytes20(0)), "invalid validationId");
+      86            0 :             require($.vInfo[vId].vType == ValidationType.wrap(0x00), "already taken");
+      87            0 :             installingPermission = ValidationId.wrap(bytes20(_internalData[0:20]));
+      88            0 :             $.vInfo[vId].vType = VALIDATION_TYPE_PERMISSION;
+      89              :         } else {
+      90            0 :             require(installingPermission == vId, "permissionId should be consistent");
+      91              :         }
+      92            0 :         $.vInfo[vId].signer = _signer;
+      93              : 
+      94            0 :         installingPermission = ValidationId.wrap(bytes20(0));
+      95              :     }
+      96              : 
+      97            0 :     function _uninstallSigner(address _signer, bytes calldata _internalData, bool _uninstallSuccess) internal {
+      98              :     }
+      99              : 
+     100            0 :     function _checkValidation(ValidationMode vMode, ValidationType vType, ValidationId vId) internal view {
+     101            0 :         ValidationStorage storage $ = _validationStorage();
+     102            0 :         ValidationId v;
+     103            0 :         if (vType == VALIDATION_TYPE_ROOT) {
+     104            0 :             v = $.root;
+     105              :         } else {
+     106            0 :             v = vId;
+     107            0 :             require($.vInfo[vId].vType == vType, InvalidValidator());
+     108              :         }
+     109              :     }
+     110              : 
+     111            0 :     function _parseNonce(uint256 nonce)
+     112              :         internal
+     113              :         pure
+     114              :         returns (ValidationMode vMode, ValidationType vType, ValidationId vId)
+     115              :     {
+     116              :         // 2bytes mode (1byte currentMode, 1byte type)
+     117              :         // 20bytes identifier
+     118              :         // 1byte mode  | 1byte type | 20bytes vId | 2byte nonceKey | 8byte nonce == 32bytes
+     119              :         assembly {
+     120            0 :             vMode := nonce
+     121            0 :             vType := shl(8, nonce)
+     122            0 :             vId := shl(16, nonce)
+     123              :         }
+     124              :     }
+     125              : 
+     126            0 :     function _verifySignature(ValidationId vId, address requester, bytes32 _hash, bytes calldata _signature)
+     127              :         internal
+     128              :         view
+     129              :         returns (uint256 validationData)
+     130              :     {
+     131            0 :         if(ValidationId.unwrap(vId) == bytes20(0)) {
+     132            0 :             return _verify7702Signature(_hash, _signature) ? 0 : 1;
+     133              :         }
+     134            0 :         IValidator validator = IValidator(getValidator(vId)); // TODO: add permission support;
+     135            0 :         validator.isValidSignatureWithSender(requester, /*NOTE: fix this */ _hash, _signature);
+     136              :     }
+     137              : 
+     138            0 :     function _validateUserOp(ValidationId vId, bytes32 opHash, PackedUserOperation calldata op, bytes calldata userOpSignature) internal returns(uint256 validationData) {
+     139            0 :         if(ValidationId.unwrap(vId) == bytes20(0)) {
+     140            0 :             return _verify7702Signature(opHash, userOpSignature) ? 0 : 1;
+     141              :         }
+     142              :     }
+     143              : 
+     144            0 :     function _verify7702Signature(bytes32 hash, bytes calldata sig) internal view returns (bool) {
+     145            0 :         return ECDSA.recover(hash, sig) == address(this);
+     146              :     }
+     147              : 
+     148            0 :     function _setRoot(Install calldata pkg) internal {
+     149            0 :         ValidationId vId;
+     150            0 :         if(pkg.moduleType == 1) {
+     151            0 :             vId = ValidationId.wrap(bytes20(pkg.module));
+     152            0 :         } else if (pkg.moduleType == 5 || pkg.moduleType == 6) {
+     153            0 :             vId = ValidationId.wrap(bytes20(pkg.internalData[0:4]));
+     154              :         } else {
+     155            0 :             revert InvalidRootValidation();
+     156              :         }
+     157            0 :         _setRoot(vId);
+     158              :     }
+     159              : 
+     160            0 :     function _setRoot(ValidationId vId) internal {
+     161            0 :         ValidationStorage storage $ = _validationStorage();
+     162            0 :         $.root = vId;
+     163              :     }
+     164              : }
+        
+
+
+ + + + +
Generated by: LCOV version 2.1-1
+
+ + + diff --git a/coverage/src/core/index-sort-f.html b/coverage/src/core/index-sort-f.html new file mode 100644 index 00000000..6be470d1 --- /dev/null +++ b/coverage/src/core/index-sort-f.html @@ -0,0 +1,165 @@ + + + + + + + LCOV - lcov.info - src/core + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - src/coreCoverageTotalHit
Test:lcov.infoLines:42.5 %19382
Test Date:2025-05-22 05:44:20Functions:45.0 %4018
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

File Sort by file nameLine Coverage Sort by line coverageFunction Coverage Sort by function coverage
Rate Total Hit Rate Total Hit
SelectorManager.sol +
0.0%
+
0.0 %160.0 %4
ValidationManager.sol +
9.2%9.2%
+
9.2 %65615.4 %132
HookManager.sol +
45.5%45.5%
+
45.5 %11550.0 %42
ModuleManager.sol +
38.5%38.5%
+
38.5 %391550.0 %63
ExecutorManager.sol +
69.2%69.2%
+
69.2 %13960.0 %53
ExecutionManager.sol +
95.9%95.9%
+
95.9 %4947100.0 %88
+
+
+ + + + +
Generated by: LCOV version 2.1-1
+
+ + + diff --git a/coverage/src/core/index-sort-l.html b/coverage/src/core/index-sort-l.html new file mode 100644 index 00000000..cee9d32c --- /dev/null +++ b/coverage/src/core/index-sort-l.html @@ -0,0 +1,165 @@ + + + + + + + LCOV - lcov.info - src/core + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - src/coreCoverageTotalHit
Test:lcov.infoLines:42.5 %19382
Test Date:2025-05-22 05:44:20Functions:45.0 %4018
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

File Sort by file nameLine Coverage Sort by line coverageFunction Coverage Sort by function coverage
Rate Total Hit Rate Total Hit
SelectorManager.sol +
0.0%
+
0.0 %160.0 %4
ValidationManager.sol +
9.2%9.2%
+
9.2 %65615.4 %132
ModuleManager.sol +
38.5%38.5%
+
38.5 %391550.0 %63
HookManager.sol +
45.5%45.5%
+
45.5 %11550.0 %42
ExecutorManager.sol +
69.2%69.2%
+
69.2 %13960.0 %53
ExecutionManager.sol +
95.9%95.9%
+
95.9 %4947100.0 %88
+
+
+ + + + +
Generated by: LCOV version 2.1-1
+
+ + + diff --git a/coverage/src/core/index.html b/coverage/src/core/index.html new file mode 100644 index 00000000..8b73bcd8 --- /dev/null +++ b/coverage/src/core/index.html @@ -0,0 +1,165 @@ + + + + + + + LCOV - lcov.info - src/core + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - src/coreCoverageTotalHit
Test:lcov.infoLines:42.5 %19382
Test Date:2025-05-22 05:44:20Functions:45.0 %4018
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

File Sort by file nameLine Coverage Sort by line coverageFunction Coverage Sort by function coverage
Rate Total Hit Rate Total Hit
ExecutionManager.sol +
95.9%95.9%
+
95.9 %4947100.0 %88
ExecutorManager.sol +
69.2%69.2%
+
69.2 %13960.0 %53
HookManager.sol +
45.5%45.5%
+
45.5 %11550.0 %42
ModuleManager.sol +
38.5%38.5%
+
38.5 %391550.0 %63
SelectorManager.sol +
0.0%
+
0.0 %160.0 %4
ValidationManager.sol +
9.2%9.2%
+
9.2 %65615.4 %132
+
+
+ + + + +
Generated by: LCOV version 2.1-1
+
+ + + diff --git a/coverage/src/index-sort-f.html b/coverage/src/index-sort-f.html new file mode 100644 index 00000000..2584308a --- /dev/null +++ b/coverage/src/index-sort-f.html @@ -0,0 +1,129 @@ + + + + + + + LCOV - lcov.info - src + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - srcCoverageTotalHit
Test:lcov.infoLines:19.2 %9919
Test Date:2025-05-22 05:44:20Functions:36.8 %197
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

File Sort by file nameLine Coverage Sort by line coverageFunction Coverage Sort by function coverage
Rate Total Hit Rate Total Hit
Lib4337.sol +
0.0%
+
0.0 %170.0 %2
Kernel.sol +
18.6%18.6%
+
18.6 %701335.7 %145
KernelFactory.sol +
50.0%50.0%
+
50.0 %12666.7 %32
+
+
+ + + + +
Generated by: LCOV version 2.1-1
+
+ + + diff --git a/coverage/src/index-sort-l.html b/coverage/src/index-sort-l.html new file mode 100644 index 00000000..0047260d --- /dev/null +++ b/coverage/src/index-sort-l.html @@ -0,0 +1,129 @@ + + + + + + + LCOV - lcov.info - src + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - srcCoverageTotalHit
Test:lcov.infoLines:19.2 %9919
Test Date:2025-05-22 05:44:20Functions:36.8 %197
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

File Sort by file nameLine Coverage Sort by line coverageFunction Coverage Sort by function coverage
Rate Total Hit Rate Total Hit
Lib4337.sol +
0.0%
+
0.0 %170.0 %2
Kernel.sol +
18.6%18.6%
+
18.6 %701335.7 %145
KernelFactory.sol +
50.0%50.0%
+
50.0 %12666.7 %32
+
+
+ + + + +
Generated by: LCOV version 2.1-1
+
+ + + diff --git a/coverage/src/index.html b/coverage/src/index.html new file mode 100644 index 00000000..0d144bfd --- /dev/null +++ b/coverage/src/index.html @@ -0,0 +1,129 @@ + + + + + + + LCOV - lcov.info - src + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - srcCoverageTotalHit
Test:lcov.infoLines:19.2 %9919
Test Date:2025-05-22 05:44:20Functions:36.8 %197
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

File Sort by file nameLine Coverage Sort by line coverageFunction Coverage Sort by function coverage
Rate Total Hit Rate Total Hit
Kernel.sol +
18.6%18.6%
+
18.6 %701335.7 %145
KernelFactory.sol +
50.0%50.0%
+
50.0 %12666.7 %32
Lib4337.sol +
0.0%
+
0.0 %170.0 %2
+
+
+ + + + +
Generated by: LCOV version 2.1-1
+
+ + + diff --git a/coverage/test/Kernel.t.sol.func-c.html b/coverage/test/Kernel.t.sol.func-c.html new file mode 100644 index 00000000..2f86a98d --- /dev/null +++ b/coverage/test/Kernel.t.sol.func-c.html @@ -0,0 +1,110 @@ + + + + + + + LCOV - lcov.info - test/Kernel.t.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - test - Kernel.t.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:81.8 %119
Test Date:2025-05-22 05:44:20Functions:80.0 %54
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by function hit count
MockValidator.onUninstall0
MockValidator.onInstall1
MockCallee.lorem2
MockCallee.forceRevert6
MockCallee.foo8
+
+
+ + + +
Generated by: LCOV version 2.1-1
+
+ + + diff --git a/coverage/test/Kernel.t.sol.func.html b/coverage/test/Kernel.t.sol.func.html new file mode 100644 index 00000000..4d2d6ed7 --- /dev/null +++ b/coverage/test/Kernel.t.sol.func.html @@ -0,0 +1,110 @@ + + + + + + + LCOV - lcov.info - test/Kernel.t.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - test - Kernel.t.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:81.8 %119
Test Date:2025-05-22 05:44:20Functions:80.0 %54
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by function hit count
MockCallee.foo8
MockCallee.forceRevert6
MockCallee.lorem2
MockValidator.onInstall1
MockValidator.onUninstall0
+
+
+ + + +
Generated by: LCOV version 2.1-1
+
+ + + diff --git a/coverage/test/Kernel.t.sol.gcov.html b/coverage/test/Kernel.t.sol.gcov.html new file mode 100644 index 00000000..27124f0b --- /dev/null +++ b/coverage/test/Kernel.t.sol.gcov.html @@ -0,0 +1,284 @@ + + + + + + + LCOV - lcov.info - test/Kernel.t.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - test - Kernel.t.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:81.8 %119
Test Date:2025-05-22 05:44:20Functions:80.0 %54
+
+ + + + + + + + +

+
            Line data    Source code
+
+       1              : pragma solidity ^0.8.0;
+       2              : 
+       3              : import {Test} from "forge-std/Test.sol";
+       4              : import {EntryPointLib} from "./utils/EntryPointLib.sol";
+       5              : import {IEntryPoint} from "account-abstraction/interfaces/IEntryPoint.sol";
+       6              : import {Kernel} from "src/Kernel.sol";
+       7              : import {KernelFactory} from "src/KernelFactory.sol";
+       8              : import {LibERC7579} from "solady/accounts/LibERC7579.sol";
+       9              : 
+      10              : contract MockValidator {
+      11              :     event MockInstall(bytes data);
+      12              :     event MockUninstall(bytes data);
+      13              : 
+      14            1 :     function onInstall(bytes calldata data) external payable {
+      15            1 :         emit MockInstall(data);
+      16              :     }
+      17              : 
+      18            0 :     function onUninstall(bytes calldata data) external payable {
+      19            0 :         emit MockUninstall(data);
+      20              :     }
+      21              : }
+      22              : 
+      23              : contract MockCallee {
+      24              :     uint256 public bar;
+      25              :     string public data;
+      26              :     event Lorem();
+      27              :     error Haha();
+      28            8 :     function foo() external {
+      29            8 :         bar++;
+      30            8 :         emit Lorem();
+      31              :     }
+      32              : 
+      33            2 :     function lorem() external {
+      34            2 :         data = "lorem ipsum";
+      35              :     }
+      36              : 
+      37            6 :     function forceRevert() external {
+      38            6 :         revert Haha();
+      39              :     }
+      40              : }
+      41              : struct Call {
+      42              :     address target;
+      43              :     uint256 value;
+      44              :     bytes data;
+      45              : }
+      46              : contract KernelTest is Test {
+      47              :     IEntryPoint ep;
+      48              :     KernelFactory factory;
+      49              :     MockValidator mockValidator;
+      50              :     Kernel kernel;
+      51              :     MockCallee callee;
+      52              :     address executor;
+      53              : 
+      54              :     modifier unitTest {
+      55              :         vm.startPrank(address(ep));
+      56              :         _;
+      57              :         vm.stopPrank();
+      58              :     }
+      59              : 
+      60              :     modifier unitTestExecutor {
+      61              :         vm.startPrank(address(executor));
+      62              :         _;
+      63              :         vm.stopPrank();
+      64              :     }
+      65              : 
+      66              :     function setUp() external {
+      67              :         ep = EntryPointLib.deploy();
+      68              :         factory = new KernelFactory(ep);
+      69              :         mockValidator = new MockValidator();
+      70              :         callee = new MockCallee();
+      71              :         executor = makeAddr("Executor");
+      72              :         _initialize();
+      73              :     }
+      74              : 
+      75              :     function _initialize() internal {
+      76              :         kernel = factory.deploy(abi.encode("Kernel Test"));
+      77              : 
+      78              :         vm.startPrank(address(ep));
+      79              :         kernel.installModule(2, executor, abi.encode(hex"", ""));
+      80              :         vm.stopPrank();
+      81              :     }
+      82              : 
+      83              :     function test_deploy() external unitTest {
+      84              :         Kernel k = factory.deploy(hex"");
+      85              :     }
+      86              : 
+      87              :     function test_install_validator() external unitTest {
+      88              :         kernel.installModule(1, address(mockValidator), abi.encode(hex"deadbeef", "InternalData"));
+      89              :     }
+      90              : 
+      91              :     function test_execute() external unitTest {
+      92              :         vm.expectEmit(address(callee));
+      93              :         emit MockCallee.Lorem();
+      94              :         kernel.execute(bytes32(0), abi.encodePacked(address(callee), uint256(0), abi.encodeWithSelector(MockCallee.foo.selector)));
+      95              :         assertEq(callee.bar(), 1);
+      96              :     }
+      97              :     
+      98              :     function test_execute_fail() external unitTest {
+      99              :         vm.expectRevert(MockCallee.Haha.selector);
+     100              :         kernel.execute(bytes32(0), abi.encodePacked(address(callee), uint256(0), abi.encodeWithSelector(MockCallee.forceRevert.selector)));
+     101              :     }
+     102              :     
+     103              :     function test_execute_fail_try() external unitTest {
+     104              :         kernel.execute(LibERC7579.encodeMode(bytes1(0x00), bytes1(0x01), bytes4(0), bytes22(0)), abi.encodePacked(address(callee), uint256(0), abi.encodeWithSelector(MockCallee.forceRevert.selector)));
+     105              :     }
+     106              : 
+     107              :     function test_execute_batch() external unitTest {
+     108              :         Call[] memory calls = new Call[](2);
+     109              :         calls[0] = Call({
+     110              :             target : address(callee),
+     111              :             value : 0,
+     112              :             data : abi.encodeWithSelector(MockCallee.foo.selector)
+     113              :         });
+     114              :         calls[1] = Call({
+     115              :             target : address(callee),
+     116              :             value : 0,
+     117              :             data : abi.encodeWithSelector(MockCallee.lorem.selector)
+     118              :         });
+     119              :         assertEq(callee.data(), "");
+     120              :         vm.expectEmit(address(callee));
+     121              :         emit MockCallee.Lorem();
+     122              :         kernel.execute(LibERC7579.encodeMode(bytes1(0x01), bytes1(0x00), bytes4(0), bytes22(0)), abi.encode(calls));
+     123              :         assertEq(callee.bar(), 1);
+     124              :         assertEq(callee.data(), "lorem ipsum");
+     125              :     }
+     126              : 
+     127              :     function test_execute_batch_fail() external unitTest {
+     128              :         Call[] memory calls = new Call[](2);
+     129              :         calls[0] = Call({
+     130              :             target : address(callee),
+     131              :             value : 0,
+     132              :             data : abi.encodeWithSelector(MockCallee.foo.selector)
+     133              :         });
+     134              :         calls[1] = Call({
+     135              :             target : address(callee),
+     136              :             value : 0,
+     137              :             data : abi.encodeWithSelector(MockCallee.forceRevert.selector)
+     138              :         });
+     139              :         assertEq(callee.data(), "");
+     140              :         vm.expectRevert(MockCallee.Haha.selector);
+     141              :         kernel.execute(LibERC7579.encodeMode(bytes1(0x01), bytes1(0x00), bytes4(0), bytes22(0)), abi.encode(calls));
+     142              :     }
+     143              : 
+     144              :     function test_execute_batch_fail_try() external unitTest {
+     145              :         Call[] memory calls = new Call[](2);
+     146              :         calls[0] = Call({
+     147              :             target : address(callee),
+     148              :             value : 0,
+     149              :             data : abi.encodeWithSelector(MockCallee.foo.selector)
+     150              :         });
+     151              :         calls[1] = Call({
+     152              :             target : address(callee),
+     153              :             value : 0,
+     154              :             data : abi.encodeWithSelector(MockCallee.forceRevert.selector)
+     155              :         });
+     156              :         assertEq(callee.data(), "");
+     157              :         kernel.execute(LibERC7579.encodeMode(bytes1(0x01), bytes1(0x01), bytes4(0), bytes22(0)), abi.encode(calls));
+     158              :         assertEq(callee.bar(), 1);
+     159              :     }
+     160              : 
+     161              :     function test_execute_delegatecall() external unitTest {
+     162              :         vm.expectEmit(address(kernel));
+     163              :         emit MockCallee.Lorem();
+     164              :         kernel.execute(LibERC7579.encodeMode(bytes1(0xff), bytes1(0x00), bytes4(0), bytes22(0)), abi.encodePacked(address(callee), abi.encodeWithSelector(MockCallee.foo.selector)));
+     165              :     }
+     166              : 
+     167              :     function test_execute_delegatecall_fail() external unitTest {
+     168              :         vm.expectRevert(MockCallee.Haha.selector);
+     169              :         kernel.execute(LibERC7579.encodeMode(bytes1(0xff), bytes1(0x00), bytes4(0), bytes22(0)), abi.encodePacked(address(callee), abi.encodeWithSelector(MockCallee.forceRevert.selector)));
+     170              :     }
+     171              :     
+     172              :     function test_execute_delegatecall_fail_try() external unitTest {
+     173              :         kernel.execute(LibERC7579.encodeMode(bytes1(0xff), bytes1(0x01), bytes4(0), bytes22(0)), abi.encodePacked(address(callee), abi.encodeWithSelector(MockCallee.forceRevert.selector)));
+     174              :     }
+     175              :     
+     176              :     function test_execute_from_executor() external unitTestExecutor {
+     177              :         vm.expectEmit(address(callee));
+     178              :         emit MockCallee.Lorem();
+     179              :         kernel.executeFromExecutor(bytes32(0), abi.encodePacked(address(callee), uint256(0), abi.encodeWithSelector(MockCallee.foo.selector)));
+     180              :         assertEq(callee.bar(), 1);
+     181              :     }
+     182              : 
+     183              :     function test_execute_batch_from_executor() external unitTestExecutor {
+     184              :         Call[] memory calls = new Call[](2);
+     185              :         calls[0] = Call({
+     186              :             target : address(callee),
+     187              :             value : 0,
+     188              :             data : abi.encodeWithSelector(MockCallee.foo.selector)
+     189              :         });
+     190              :         calls[1] = Call({
+     191              :             target : address(callee),
+     192              :             value : 0,
+     193              :             data : abi.encodeWithSelector(MockCallee.lorem.selector)
+     194              :         });
+     195              :         assertEq(callee.data(), "");
+     196              :         vm.expectEmit(address(callee));
+     197              :         emit MockCallee.Lorem();
+     198              :         kernel.executeFromExecutor(LibERC7579.encodeMode(bytes1(0x01), bytes1(0x00), bytes4(0), bytes22(0)), abi.encode(calls));
+     199              :         assertEq(callee.bar(), 1);
+     200              :         assertEq(callee.data(), "lorem ipsum");
+     201              :     }
+     202              : 
+     203              :     function test_execute_delegatecall_from_executor() external unitTestExecutor {
+     204              :         vm.expectEmit(address(kernel));
+     205              :         emit MockCallee.Lorem();
+     206              :         kernel.executeFromExecutor(LibERC7579.encodeMode(bytes1(0xff), bytes1(0x00), bytes4(0), bytes22(0)), abi.encodePacked(address(callee), abi.encodeWithSelector(MockCallee.foo.selector)));
+     207              :     }
+     208              : }
+        
+
+
+ + + + +
Generated by: LCOV version 2.1-1
+
+ + + diff --git a/coverage/test/index-sort-f.html b/coverage/test/index-sort-f.html new file mode 100644 index 00000000..2bc33aec --- /dev/null +++ b/coverage/test/index-sort-f.html @@ -0,0 +1,105 @@ + + + + + + + LCOV - lcov.info - test + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - testCoverageTotalHit
Test:lcov.infoLines:81.8 %119
Test Date:2025-05-22 05:44:20Functions:80.0 %54
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

File Sort by file nameLine Coverage Sort by line coverageFunction Coverage Sort by function coverage
Rate Total Hit Rate Total Hit
Kernel.t.sol +
81.8%81.8%
+
81.8 %11980.0 %54
+
+
+ + + + +
Generated by: LCOV version 2.1-1
+
+ + + diff --git a/coverage/test/index-sort-l.html b/coverage/test/index-sort-l.html new file mode 100644 index 00000000..c3f81dfc --- /dev/null +++ b/coverage/test/index-sort-l.html @@ -0,0 +1,105 @@ + + + + + + + LCOV - lcov.info - test + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - testCoverageTotalHit
Test:lcov.infoLines:81.8 %119
Test Date:2025-05-22 05:44:20Functions:80.0 %54
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

File Sort by file nameLine Coverage Sort by line coverageFunction Coverage Sort by function coverage
Rate Total Hit Rate Total Hit
Kernel.t.sol +
81.8%81.8%
+
81.8 %11980.0 %54
+
+
+ + + + +
Generated by: LCOV version 2.1-1
+
+ + + diff --git a/coverage/test/index.html b/coverage/test/index.html new file mode 100644 index 00000000..ef49a5ce --- /dev/null +++ b/coverage/test/index.html @@ -0,0 +1,105 @@ + + + + + + + LCOV - lcov.info - test + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - testCoverageTotalHit
Test:lcov.infoLines:81.8 %119
Test Date:2025-05-22 05:44:20Functions:80.0 %54
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

File Sort by file nameLine Coverage Sort by line coverageFunction Coverage Sort by function coverage
Rate Total Hit Rate Total Hit
Kernel.t.sol +
81.8%81.8%
+
81.8 %11980.0 %54
+
+
+ + + + +
Generated by: LCOV version 2.1-1
+
+ + + diff --git a/coverage/test/utils/EntryPointLib.sol.func-c.html b/coverage/test/utils/EntryPointLib.sol.func-c.html new file mode 100644 index 00000000..2b60c0bb --- /dev/null +++ b/coverage/test/utils/EntryPointLib.sol.func-c.html @@ -0,0 +1,82 @@ + + + + + + + LCOV - lcov.info - test/utils/EntryPointLib.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - test/utils - EntryPointLib.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:100.0 %44
Test Date:2025-05-22 05:44:20Functions:100.0 %11
+
+ +
+ + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by function hit count
EntryPointLib.deploy14
+
+
+ + + +
Generated by: LCOV version 2.1-1
+
+ + + diff --git a/coverage/test/utils/EntryPointLib.sol.func.html b/coverage/test/utils/EntryPointLib.sol.func.html new file mode 100644 index 00000000..3e1d76d2 --- /dev/null +++ b/coverage/test/utils/EntryPointLib.sol.func.html @@ -0,0 +1,82 @@ + + + + + + + LCOV - lcov.info - test/utils/EntryPointLib.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - test/utils - EntryPointLib.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:100.0 %44
Test Date:2025-05-22 05:44:20Functions:100.0 %11
+
+ +
+ + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by function hit count
EntryPointLib.deploy14
+
+
+ + + +
Generated by: LCOV version 2.1-1
+
+ + + diff --git a/coverage/test/utils/EntryPointLib.sol.gcov.html b/coverage/test/utils/EntryPointLib.sol.gcov.html new file mode 100644 index 00000000..29e7ab88 --- /dev/null +++ b/coverage/test/utils/EntryPointLib.sol.gcov.html @@ -0,0 +1,92 @@ + + + + + + + LCOV - lcov.info - test/utils/EntryPointLib.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - test/utils - EntryPointLib.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:100.0 %44
Test Date:2025-05-22 05:44:20Functions:100.0 %11
+
+ + + + + + + + +

+
            Line data    Source code
+
+       1              : pragma solidity ^0.8.0;
+       2              : 
+       3              : import {IEntryPoint} from "account-abstraction/interfaces/IEntryPoint.sol";
+       4              : 
+       5              : bytes constant ENTRYPOINT_0_8_INITCODE =
+       6              :     hex"0a59dbff790c23c976a548690c27297883cc66b4c67024f9117b0238995e35e96101806040523461019557604051610018604082610199565b600781526020810190664552433433333760c81b82526040519161003d604084610199565b600183526020830191603160f81b8352610056816101bc565b6101205261006384610357565b61014052519020918260e05251902080610100524660a0526040519060208201927f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f8452604083015260608201524660808201523060a082015260a081526100cc60c082610199565b5190206080523060c0526040516104f58082016001600160401b0381118382101761018157829161597a833903905ff0801561017657610160526040516154ea9081610490823960805181613511015260a051816135ce015260c051816134e2015260e051816135600152610100518161358601526101205181611884015261014051816118ad0152610160518181816116ce015281816120a801528181615061015261538c0152f35b6040513d5f823e3d90fd5b634e487b7160e01b5f52604160045260245ffd5b5f80fd5b601f909101601f19168101906001600160401b0382119082101761018157604052565b908151602081105f14610236575090601f8151116101f65760208151910151602082106101e7571790565b5f198260200360031b1b161790565b604460209160405192839163305a27a960e01b83528160048401528051918291826024860152018484015e5f828201840152601f01601f19168101030190fd5b6001600160401b03811161018157600254600181811c9116801561034d575b602082101461033957601f8111610306575b50602092601f82116001146102a557928192935f9261029a575b50508160011b915f199060031b1c19161760025560ff90565b015190505f80610281565b601f1982169360025f52805f20915f5b8681106102ee57508360019596106102d6575b505050811b0160025560ff90565b01515f1960f88460031b161c191690555f80806102c8565b919260206001819286850151815501940192016102b5565b60025f52601f60205f20910160051c810190601f830160051c015b81811061032e5750610267565b5f8155600101610321565b634e487b7160e01b5f52602260045260245ffd5b90607f1690610255565b908151602081105f14610382575090601f8151116101f65760208151910151602082106101e7571790565b6001600160401b03811161018157600354600181811c91168015610485575b602082101461033957601f8111610452575b50602092601f82116001146103f157928192935f926103e6575b50508160011b915f199060031b1c19161760035560ff90565b015190505f806103cd565b601f1982169360035f52805f20915f5b86811061043a5750836001959610610422575b505050811b0160035560ff90565b01515f1960f88460031b161c191690555f8080610414565b91926020600181928685015181550194019201610401565b60035f52601f60205f20910160051c810190601f830160051c015b81811061047a57506103b3565b5f815560010161046d565b90607f16906103a156fe6101606040526004361015610024575b3615610019575f80fd5b610022336131f4565b005b5f610140525f3560e01c806242dc53146125d957806301ffc9a7146124875780630396cb60146120cc57806309ccb8801461205b5780630bd28e3b14611fbf57806313c65a6e14611f84578063154e58dc14611f295780631b2e01b814611e93578063205c287814611cf257806322cdde4c14611c6e57806335567e1a14611bb45780635287ce1214611a9457806370a0823114611a29578063765e827f1461198b57806384b0196e1461184b578063850aaf62146117865780639b249f6914611622578063b760faf9146115e1578063bb9fe6bf146113f2578063c23a5cea1461114f5763dbed18e00361000f5734610ec95761012136612d56565b6101005260e052610130613824565b6101405190815b60e0518110610f2e575061014a8261303a565b61012052610140516080526101405160c0525b60e05160c0511061029b577fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f9726101405161014051a161014051608081905290815b60e05181106101e1576101b48361010051614a19565b610140517f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005d6101405180f35b6102436101f18260e05185613267565b73ffffffffffffffffffffffffffffffffffffffff610212602083016132fb565b167f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d6101405161014051a2806132a7565b9061014051915b80831061025c5750505060010161019e565b909194600190610289610270888587613109565b61027f60805161012051613176565b519060805161437c565b0195816080510160805201919061024a565b6102aa60c05160e05183613267565b73ffffffffffffffffffffffffffffffffffffffff6102d860206102ce84806132a7565b60a05293016132fb565b61014051911691905b60a05181106103055750505060a05160805101608052600160c0510160c05261015d565b610316816080510161012051613176565b516103248260a05185613109565b61014051915a81519273ffffffffffffffffffffffffffffffffffffffff61034b826132fb565b168452602081810135908501526fffffffffffffffffffffffffffffffff6080808301358281166060880152811c604087015260a083013560c0808801919091528301359182166101008701521c6101208501526103ac60e082018261331c565b9081610e15575b5050604051936103c282612ee9565b6020850152846040526040810151946effffffffffffffffffffffffffffff8660c08401511760608401511760808401511760a084015117610100840151176101208401511711610daf5750604081015160608201510160808201510160a08201510160c0820151016101008201510294856040860152845173ffffffffffffffffffffffffffffffffffffffff60e08183511692610475898d61046960408b018b61331c565b92909160805101614fb5565b0151169661014051978015610d7e575b87516040810151905173ffffffffffffffffffffffffffffffffffffffff169061014051506040519a8b8960208d01519260208301937f19822f7c00000000000000000000000000000000000000000000000000000000855260248401926104ec93615460565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081018d5261051c908d612c2d565b61014051908c5190846101405190602095f161014051519a3d602003610d73575b60405215610c80575015610c02575b505073ffffffffffffffffffffffffffffffffffffffff825116602083015190610140515260016020526040610140512077ffffffffffffffffffffffffffffffffffffffffffffffff8260401c165f5260205267ffffffffffffffff60405f20918254926105ba84612e80565b90551603610b99575a840311610b305760e0015160609073ffffffffffffffffffffffffffffffffffffffff16610827575b73ffffffffffffffffffffffffffffffffffffffff949260a0859360809360606106219801520135905a900301910152614f15565b911685036107be576107555761064b73ffffffffffffffffffffffffffffffffffffffff91614f15565b91166106ec5761065d576001016102e1565b60a490604051907f220266b600000000000000000000000000000000000000000000000000000000825260805101600482015260406024820152602160448201527f41413332207061796d61737465722065787069726564206f72206e6f7420647560648201527f65000000000000000000000000000000000000000000000000000000000000006084820152fd5b608482604051907f220266b600000000000000000000000000000000000000000000000000000000825260805101600482015260406024820152601460448201527f41413334207369676e6174757265206572726f720000000000000000000000006064820152fd5b608482604051907f220266b600000000000000000000000000000000000000000000000000000000825260805101600482015260406024820152601760448201527f414132322065787069726564206f72206e6f74206475650000000000000000006064820152fd5b608483604051907f220266b600000000000000000000000000000000000000000000000000000000825260805101600482015260406024820152601460448201527f41413234207369676e6174757265206572726f720000000000000000000000006064820152fd5b9897969594505a9883519961085b73ffffffffffffffffffffffffffffffffffffffff60e08d015116604087015190615482565b15610ac75760807f52b7512c000000000000000000000000000000000000000000000000000000009798999a9b01516040516108dc816108b060208a015160408b015190602084019d8e528960248501615460565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282612c2d565b8651608073ffffffffffffffffffffffffffffffffffffffff60e08301511691015161014051918b61014051928551926101405191f1983d908161014051843e51948251604084019b8c519015918215610abb575b508115610a8b575b50610a065750601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09101160191826040525a90031161097a5750946105ec565b80887f220266b60000000000000000000000000000000000000000000000000000000060a4935260805101600482015260406024820152602760448201527f41413336206f766572207061796d6173746572566572696669636174696f6e4760648201527f61734c696d6974000000000000000000000000000000000000000000000000006084820152fd5b8b610a87610a1261349e565b6040519384937f65c8fd4d0000000000000000000000000000000000000000000000000000000085526080510160048501526024840152600d60648401527f4141333320726576657274656400000000000000000000000000000000000000608484015260a0604484015260a4830190612de9565b0390fd5b9050601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa084019101105f610939565b6040141591505f610931565b608487604051907f220266b600000000000000000000000000000000000000000000000000000000825260805101600482015260406024820152601e60448201527f41413331207061796d6173746572206465706f73697420746f6f206c6f7700006064820152fd5b608487604051907f220266b600000000000000000000000000000000000000000000000000000000825260805101600482015260406024820152601e60448201527f41413236206f76657220766572696669636174696f6e4761734c696d697400006064820152fd5b608488604051907f220266b600000000000000000000000000000000000000000000000000000000825260805101600482015260406024820152601a60448201527f4141323520696e76616c6964206163636f756e74206e6f6e63650000000000006064820152fd5b610c0b91615482565b15610c17578b8061054c565b608488604051907f220266b600000000000000000000000000000000000000000000000000000000825260805101600482015260406024820152601760448201527f41413231206469646e2774207061792070726566756e640000000000000000006064820152fd5b8b903b610cf057608490604051907f220266b600000000000000000000000000000000000000000000000000000000825260805101600482015260406024820152601960448201527f41413230206163636f756e74206e6f74206465706c6f796564000000000000006064820152fd5b610cf861349e565b90610a876040519283927f65c8fd4d00000000000000000000000000000000000000000000000000000000845260805101600484015260606024840152600d60648401527f4141323320726576657274656400000000000000000000000000000000000000608484015260a0604484015260a4830190612de9565b61014051915061053d565b6101408051849052516020819052604090205490985081811115610da85750610140515b97610485565b8103610da2565b80887f220266b6000000000000000000000000000000000000000000000000000000006084935260805101600482015260406024820152601860448201527f41413934206761732076616c756573206f766572666c6f7700000000000000006064820152fd5b60348210610ed05781601411610ec95780359160248110610ec957603411610ec9576024810135608090811c60a0880152601490910135811c90860152606081901c15610e6b5760601c60e085015289806103b3565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4141393820696e76616c6964207061796d6173746572000000000000000000006044820152fd5b6101405180fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4141393320696e76616c6964207061796d6173746572416e64446174610000006044820152fd5b610f3b8160e05184613267565b92610f4684806132a7565b919073ffffffffffffffffffffffffffffffffffffffff610f69602088016132fb565b16956001871461111d5786610f86575b5050019250600101610137565b806040610f9492019061331c565b91873b15610ec957916040519283917f2dd8113300000000000000000000000000000000000000000000000000000000835286604484016040600486015252606483019160648860051b8501019281610140517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee182360301915b8b82106110c357505050505081611054917ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8580950301602485015261014051956131b6565b0381610140518a5af190816110a8575b5061109b57847f86a9f750000000000000000000000000000000000000000000000000000000006101405152600452602461014051fd5b929350839260015f610f79565b610140516110b591612c2d565b61014051610ec9575f611064565b9193967fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9c90879294969703018552863584811215610ec957602061110c600193858394016133bd565b98019501920188969594939161100e565b867f86a9f750000000000000000000000000000000000000000000000000000000006101405152600452602461014051fd5b34610ec95760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec957611186612cde565b3361014051526101405160205260016040610140512001908154916dffffffffffffffffffffffffffff8360081c169283156113945760981c65ffffffffffff1680156113365742106112d85780547fffffffffffffff000000000000000000000000000000000000000000000000ff1690556040805173ffffffffffffffffffffffffffffffffffffffff831681526020810184905233917fb7c918e0e249f999e965cafeb6c664271b3f4317d296461500e71da39f0cbda391a2610140519182918291829173ffffffffffffffffffffffffffffffffffffffff165af161126d612eba565b501561127a576101405180f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f6661696c656420746f207769746864726177207374616b6500000000000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f5374616b65207769746864726177616c206973206e6f742064756500000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f6d7573742063616c6c20756e6c6f636b5374616b6528292066697273740000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f207374616b6520746f2077697468647261770000000000000000000000006044820152fd5b34610ec957610140517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec9573361014051526101405160205260016040610140512001805463ffffffff8160781c169081156115835760ff16156115255765ffffffffffff4216019065ffffffffffff82116114f25780547fffffffffffffff000000000000ffffffffffffffffffffffffffffffffffff001678ffffffffffff00000000000000000000000000000000000000609884901b1617905560405165ffffffffffff909116815233907ffa9b3c14cc825c412c9ed81b3ba365a5b459439403f18829e572ed53a4180f0a90602090a26101405180f35b7f4e487b710000000000000000000000000000000000000000000000000000000061014051526011600452602461014051fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f616c726561647920756e7374616b696e670000000000000000000000000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f6e6f74207374616b6564000000000000000000000000000000000000000000006044820152fd5b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec95761161b611616612cde565b6131f4565b6101405180f35b34610ec95760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec95760043567ffffffffffffffff8111610ec95760206116766116b1923690600401612d01565b60405193849283927f570e1a3600000000000000000000000000000000000000000000000000000000845285600485015260248401916131b6565b03816101405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165af180156117785773ffffffffffffffffffffffffffffffffffffffff916101405191611749575b507f6ca7b80600000000000000000000000000000000000000000000000000000000610140515216600452602461014051fd5b61176b915060203d602011611771575b6117638183612c2d565b81019061318a565b82611716565b503d611759565b6040513d61014051823e3d90fd5b34610ec95760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec9576117bd612cde565b60243567ffffffffffffffff8111610ec9576117dd903690600401612d01565b604051929181908437820190610140518252610140519280610140519303915af4611806612eba565b90610a876040519283927f9941055400000000000000000000000000000000000000000000000000000000845215156004840152604060248401526044830190612de9565b34610ec957610140517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec9576119296118a87f0000000000000000000000000000000000000000000000000000000000000000614ccf565b6118d17f0000000000000000000000000000000000000000000000000000000000000000614e45565b60405190602090611937906118e68385612c2d565b6101405184525f3681376040519586957f0f00000000000000000000000000000000000000000000000000000000000000875260e08588015260e0870190612de9565b908582036040870152612de9565b4660608501523060808501526101405160a085015283810360c0850152818084519283815201930191610140515b82811061197457505050500390f35b835185528695509381019392810192600101611965565b34610ec95761199936612d56565b6119a4929192613824565b6119ad8361303a565b6119b8818585613898565b5061014051927fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f9728480a161014051915b8583106119f9576101b48585614a19565b909193600190611a1f611a0d878987613109565b611a178886613176565b51908861437c565b01940191906119e8565b34610ec95760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec95773ffffffffffffffffffffffffffffffffffffffff611a75612cde565b1661014051526101405160205260206040610140512054604051908152f35b34610ec95760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec95773ffffffffffffffffffffffffffffffffffffffff611ae0612cde565b604051611aec81612bab565b6101405181526101405160208201526101405160408201526101405160608201526080610140519101521661014051526101405160205260a06040610140512065ffffffffffff604051611b3f81612bab565b63ffffffff60018454948584520154916dffffffffffffffffffffffffffff6020820160ff8516151581526040830190828660081c1682528660806060860195878960781c168752019660981c1686526040519788525115156020880152511660408601525116606084015251166080820152f35b34610ec95760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec9576020611bed612cde565b73ffffffffffffffffffffffffffffffffffffffff611c0a612d2f565b91166101405152600182526040610140512077ffffffffffffffffffffffffffffffffffffffffffffffff82165f52825260405f20547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000006040519260401b16178152f35b34610ec95760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec95760043567ffffffffffffffff8111610ec9576101207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8236030112610ec957611cea602091600401612ee9565b604051908152f35b34610ec95760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec957611d29612cde565b6024359033610140515261014051602052604061014051208054808411611e355783611d5491612ead565b90556040805173ffffffffffffffffffffffffffffffffffffffff831681526020810184905233917fd1c19fbcd4551a5edfb66d43d2e337c04837afda3482b42bdf569a8fccdae5fb91a2610140519182918291829173ffffffffffffffffffffffffffffffffffffffff165af1611dca612eba565b5015611dd7576101405180f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6661696c656420746f20776974686472617700000000000000000000000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f576974686472617720616d6f756e7420746f6f206c61726765000000000000006044820152fd5b34610ec95760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec957611eca612cde565b73ffffffffffffffffffffffffffffffffffffffff611ee7612d2f565b91166101405152600160205277ffffffffffffffffffffffffffffffffffffffffffffffff6040610140512091165f52602052602060405f2054604051908152f35b34610ec957610140517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec95760206040517f29a0bca4af4be3421398da00295e58e6d7de38cb492214754cb6a47507dd6f8e8152f35b34610ec957610140517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec9576020611cea6134cb565b34610ec95760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec95760043577ffffffffffffffffffffffffffffffffffffffffffffffff81168103610ec957336101405152600160205277ffffffffffffffffffffffffffffffffffffffffffffffff6040610140512091165f5260205260405f206120528154612e80565b90556101405180f35b34610ec957610140517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec957602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec95760043563ffffffff8116809103610ec957336101405152610140516020526040610140512090801561242957600182015463ffffffff8160781c1682106123cb57612155906dffffffffffffffffffffffffffff349160081c16612e46565b91821561236d576dffffffffffffffffffffffffffff831161230f57546040516122d79161218282612bab565b815265ffffffffffff602082019160018352604081016dffffffffffffffffffffffffffff87168152606082019086825260016080840193610140518552336101405152610140516020526040610140512090518155019451151560ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008754169116178555517fffffffffffffffffffffffffffffffffff0000000000000000000000000000ff6effffffffffffffffffffffffffff008087549360081b16169116178455517fffffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffff72ffffffff0000000000000000000000000000008086549360781b1616911617835551167fffffffffffffff000000000000ffffffffffffffffffffffffffffffffffffff78ffffffffffff0000000000000000000000000000000000000083549260981b169116179055565b60405191825260208201527fa5ae833d0bb1dcd632d98a8b70973e8516812898e19bf27b70071ebc8dc52c0160403392a26101405180f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f7374616b65206f766572666c6f770000000000000000000000000000000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6e6f207374616b652073706563696669656400000000000000000000000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f63616e6e6f7420646563726561736520756e7374616b652074696d65000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f6d757374207370656369667920756e7374616b652064656c61790000000000006044820152fd5b34610ec95760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec9576004357fffffffff000000000000000000000000000000000000000000000000000000008116809103610ec957807f6930d3ee00000000000000000000000000000000000000000000000000000000602092149081156125af575b8115612585575b811561255b575b8115612531575b506040519015158152f35b7f01ffc9a70000000000000000000000000000000000000000000000000000000091501482612526565b7f3e84f021000000000000000000000000000000000000000000000000000000008114915061251f565b7fcf28ef970000000000000000000000000000000000000000000000000000000081149150612518565b7f989ccc580000000000000000000000000000000000000000000000000000000081149150612511565b34612a32576102007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112612a325760043567ffffffffffffffff8111612a325736602382011215612a325761263a903690602481600401359101612ca8565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc36016101c08112612a32576101406040519161267683612bab565b12612a325760405161268781612bf4565b60243573ffffffffffffffffffffffffffffffffffffffff81168103612a3257815260443560208201526064356040820152608435606082015260a435608082015260c43560a082015260e43560c08201526101043573ffffffffffffffffffffffffffffffffffffffff81168103612a325760e082015261012435610100820152610144356101208201528152602081019161016435835260408201906101843582526101a435606084015260808301916101c43583526101e43567ffffffffffffffff8111612a3257612760903690600401612d01565b955a90303303612b4d578651606081015195603f5a0260061c61271060a084015189010111612b25575f9681519182612a6b575b5050505050906127ac915a9003855101963691612ca8565b925a93855161010081015161012082015148018082105f14612a635750975b6127f873ffffffffffffffffffffffffffffffffffffffff60e08401511694518203606084015190614b09565b01925f928161290e5750505173ffffffffffffffffffffffffffffffffffffffff16945b5a900301019485029051928184105f146128ba5750506003811015612887576002036128595760209281611cea929361285481614c2a565b614b28565b7fdeadaa51000000000000000000000000000000000000000000000000000000006101405152602061014051fd5b7f4e487b710000000000000000000000000000000000000000000000000000000061014051526021600452602461014051fd5b816128f0929594969396039073ffffffffffffffffffffffffffffffffffffffff165f525f60205260405f209081540180915590565b5060038410156128875782612909926020951590614ba9565b611cea565b909691878251612921575b50505061281c565b90919293505a926003881015612a365760028803612957575b505060a061294e925a900391015190614b09565b90888080612919565b60a083015191803b15612a32578b925f92836129b3938c8b88604051998a98899788957f7c627b210000000000000000000000000000000000000000000000000000000087526004870152608060248701526084860190612de9565b9202604484015260648301520393f19081612a1d575b50612a1357610a876129d961349e565b6040519182917fad7954bc000000000000000000000000000000000000000000000000000000008352602060048401526024830190612de9565b60a061294e61293a565b5f612a2791612c2d565b5f610140528a6129c9565b5f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b9050976127cb565b915f9291838093602073ffffffffffffffffffffffffffffffffffffffff885116910192f115612a9e575b808080612794565b6127ac9392955060405191612ab161349e565b908151612aca575b505050604052600193909188612a96565b7f1c4fada7374c0a9ee8841fc38afe82932dc0f8e69012e927f061a8bae611a201905191602073ffffffffffffffffffffffffffffffffffffffff855116940151612b1a60405192839283612e2c565b0390a3888080612ab9565b7fdeaddead000000000000000000000000000000000000000000000000000000005f5260205ffd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4141393220696e7465726e616c2063616c6c206f6e6c790000000000000000006044820152fd5b60a0810190811067ffffffffffffffff821117612bc757604052565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b610140810190811067ffffffffffffffff821117612bc757604052565b6060810190811067ffffffffffffffff821117612bc757604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117612bc757604052565b67ffffffffffffffff8111612bc757601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b929192612cb482612c6e565b91612cc26040519384612c2d565b829481845281830111612a32578281602093845f960137010152565b6004359073ffffffffffffffffffffffffffffffffffffffff82168203612a3257565b9181601f84011215612a325782359167ffffffffffffffff8311612a325760208381860195010111612a3257565b6024359077ffffffffffffffffffffffffffffffffffffffffffffffff82168203612a3257565b9060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc830112612a325760043567ffffffffffffffff8111612a325760040182601f82011215612a325780359267ffffffffffffffff8411612a32576020808301928560051b010111612a3257919060243573ffffffffffffffffffffffffffffffffffffffff81168103612a325790565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f602080948051918291828752018686015e5f8582860101520116010190565b604090612e43939281528160208201520190612de9565b90565b91908201809211612e5357565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114612e535760010190565b91908203918211612e5357565b3d15612ee4573d90612ecb82612c6e565b91612ed96040519384612c2d565b82523d5f602084013e565b606090565b604290612ef5816135f4565b612efd6134cb565b91612f07816132fb565b91801561300557905b60c0612f1f606083018361331c565b90816040519182372091612f3660e082018261331c565b908160405191823720926040519473ffffffffffffffffffffffffffffffffffffffff60208701977f29a0bca4af4be3421398da00295e58e6d7de38cb492214754cb6a47507dd6f8e895216604087015260208301356060870152608086015260a085015260808101358285015260a081013560e085015201356101008301526101208201526101208152612fcd61014082612c2d565b519020604051917f19010000000000000000000000000000000000000000000000000000000000008352600283015260228201522090565b50613013604082018261331c565b90816040519182372090612f10565b67ffffffffffffffff8111612bc75760051b60200190565b9061304482613022565b6130516040519182612c2d565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe061307f8294613022565b01905f5b82811061308f57505050565b60209060405161309e81612bab565b6040516130aa81612bf4565b5f81525f848201525f60408201525f60608201525f60808201525f60a08201525f60c08201525f60e08201525f6101008201525f61012082015281525f838201525f60408201525f60608201525f608082015282828501015201613083565b91908110156131495760051b810135907ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee181360301821215612a32570190565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b80518210156131495760209160051b010190565b90816020910312612a32575173ffffffffffffffffffffffffffffffffffffffff81168103612a325790565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe093818652868601375f8582860101520116010190565b7f2da466a7b24304f47e87fa2e1e5a81b9831ce54fec19055ce277ca2f39ba42c4602073ffffffffffffffffffffffffffffffffffffffff61325b348573ffffffffffffffffffffffffffffffffffffffff165f525f60205260405f209081540180915590565b936040519485521692a2565b91908110156131495760051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa181360301821215612a32570190565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215612a32570180359067ffffffffffffffff8211612a3257602001918160051b36038313612a3257565b3573ffffffffffffffffffffffffffffffffffffffff81168103612a325790565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215612a32570180359067ffffffffffffffff8211612a3257602001918136038313612a3257565b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe182360301811215612a3257016020813591019167ffffffffffffffff8211612a32578136038313612a3257565b80359173ffffffffffffffffffffffffffffffffffffffff83168303612a325773ffffffffffffffffffffffffffffffffffffffff612e43931681526020820135602082015261348f61348361344a61342f61341c604087018761336d565b61012060408801526101208701916131b6565b61343c606087018761336d565b9086830360608801526131b6565b6080850135608085015260a085013560a085015260c085013560c085015261347560e086018661336d565b9085830360e08701526131b6565b9261010081019061336d565b916101008185039101526131b6565b3d61080081116134c2575b604051906020818301016040528082525f602083013e90565b506108006134a9565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163014806135cb575b15613533577f000000000000000000000000000000000000000000000000000000000000000090565b60405160208101907f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f82527f000000000000000000000000000000000000000000000000000000000000000060408201527f000000000000000000000000000000000000000000000000000000000000000060608201524660808201523060a082015260a081526135c560c082612c2d565b51902090565b507f0000000000000000000000000000000000000000000000000000000000000000461461350a565b613601604082018261331c565b909161360d8284614c7a565b1561381d5761361b906132fb565b60175f80833c5f51907fef010000000000000000000000000000000000000000000000000000000000007fffffff000000000000000000000000000000000000000000000000000000000083160361375b575060181b91601482116136bb5750506040517fffffffffffffffffffffffffffffffffffffffff000000000000000000000000808060208401941616168252601481526135c5603482612c2d565b81601411612a325760206135c5916040519384917fffffffffffffffffffffffffffffffffffffffff000000000000000000000000808086860199161616875260147fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec83019101603484013781015f8382015203017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282612c2d565b3b156137bf5760646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f6e6f7420616e204549502d373730322064656c656761746500000000000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f73656e64657220686173206e6f20636f646500000000000000000000000000006044820152fd5b5050505f90565b7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005c6138705760017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005d565b7f3ee5aeb5000000000000000000000000000000000000000000000000000000005f5260045ffd5b92919092835f5b8181106138ac5750505050565b6138b68185613176565b516138c2828486613109565b5f915a81519273ffffffffffffffffffffffffffffffffffffffff6138e6826132fb565b168452602081013560208501526080810135936fffffffffffffffffffffffffffffffff8560801c951694604082019060608301968752815260c0820160a0840135815260c0840135906fffffffffffffffffffffffffffffffff8260801c9216916101208501906101008601938452815261396560e087018761331c565b9081614316575b505060405161397a87612ee9565b9960208a019a8b528160405285519586855117825117926effffffffffffffffffffffffffffff60808a01948551179560a08b0196875117895117905117116142b45750519051019051019051019051019051029560408601918783528973ffffffffffffffffffffffffffffffffffffffff60e08951613a0f8b8483511695613a0760408d018d61331c565b929091614fb5565b015116985f99801561428d575b89516040810151905173ffffffffffffffffffffffffffffffffffffffff1680916040519d8e808d8b519360208301947f19822f7c0000000000000000000000000000000000000000000000000000000086526024840192613a7d93615460565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081018252613aad9082612c2d565b51905f6020948194f15f519c3d602003614285575b6040521561419a575015614120575b505073ffffffffffffffffffffffffffffffffffffffff8451166020850151905f52600160205260405f2077ffffffffffffffffffffffffffffffffffffffffffffffff8260401c165f5260205267ffffffffffffffff60405f2091825492613b3984612e80565b905516036140bb575a8603116140565773ffffffffffffffffffffffffffffffffffffffff60e0606094015116613d96575b505073ffffffffffffffffffffffffffffffffffffffff949260a085936080936060613ba29801520135905a900301910152614f15565b9116613d3157613ccc57613bca73ffffffffffffffffffffffffffffffffffffffff91614f15565b9116613c6757613bdc5760010161389f565b60a490604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152602160448201527f41413332207061796d61737465722065787069726564206f72206e6f7420647560648201527f65000000000000000000000000000000000000000000000000000000000000006084820152fd5b608482604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601460448201527f41413334207369676e6174757265206572726f720000000000000000000000006064820152fd5b608482604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601760448201527f414132322065787069726564206f72206e6f74206475650000000000000000006064820152fd5b608483604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601460448201527f41413234207369676e6174757265206572726f720000000000000000000000006064820152fd5b909c9b9a99989796505a9085519d60e08f015173ffffffffffffffffffffffffffffffffffffffff168151613dca91615482565b15613ff157613e1d7f52b7512c00000000000000000000000000000000000000000000000000000000999a9b9c9d9e9f60800151926108b060405193849251905190602084019d8e528960248501615460565b5f8088518b82608073ffffffffffffffffffffffffffffffffffffffff60e08501511693015192865193f1983d90815f843e51948251604084019b8c519015918215613fe5575b508115613fb5575b50613f385750601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09101160191826040525a900311613eb05750948260a0613b6b565b80887f220266b60000000000000000000000000000000000000000000000000000000060a49352600482015260406024820152602760448201527f41413336206f766572207061796d6173746572566572696669636174696f6e4760648201527f61734c696d6974000000000000000000000000000000000000000000000000006084820152fd5b8b610a87613f4461349e565b6040519384937f65c8fd4d00000000000000000000000000000000000000000000000000000000855260048501526024840152600d60648401527f4141333320726576657274656400000000000000000000000000000000000000608484015260a0604484015260a4830190612de9565b9050601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa084019101105f613e6c565b6040141591505f613e64565b608489604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601e60448201527f41413331207061796d6173746572206465706f73697420746f6f206c6f7700006064820152fd5b608489604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601e60448201527f41413236206f76657220766572696669636174696f6e4761734c696d697400006064820152fd5b60848a604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601a60448201527f4141323520696e76616c6964206163636f756e74206e6f6e63650000000000006064820152fd5b61412991615482565b15614135575f80613ad1565b60848a604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601760448201527f41413231206469646e2774207061792070726566756e640000000000000000006064820152fd5b8d903b61420657608490604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601960448201527f41413230206163636f756e74206e6f74206465706c6f796564000000000000006064820152fd5b61420e61349e565b90610a876040519283927f65c8fd4d000000000000000000000000000000000000000000000000000000008452600484015260606024840152600d60648401527f4141323320726576657274656400000000000000000000000000000000000000608484015260a0604484015260a4830190612de9565b5f9150613ac2565b9950815f525f60205260405f20548181115f146142ad57505f5b99613a1c565b81036142a7565b808f7f220266b60000000000000000000000000000000000000000000000000000000060849352600482015260406024820152601860448201527f41413934206761732076616c756573206f766572666c6f7700000000000000006064820152fd5b60348210610ed05781601411612a3257803560601c9160248110612a3257601482013590603411612a32576fffffffffffffffffffffffffffffffff60248193013560801c1660a089015260801c1660808701528015610e6b5760e08601525f8061396c565b9092915a60608201516040519586614397606083018361331c565b5f60038211614a11575b7fffffffff00000000000000000000000000000000000000000000000000000000167f8dd7712f00000000000000000000000000000000000000000000000000000000036148a3575050505f6144ae6145a261443c61446e602095868a01516040519384927f8dd7712f000000000000000000000000000000000000000000000000000000008a8501526040602485015260648401906133bd565b906044830152037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282612c2d565b6108b06040519384927e42dc5300000000000000000000000000000000000000000000000000000000888501526102006024850152610224840190612de9565b614571604484018b60806101a091610120815173ffffffffffffffffffffffffffffffffffffffff8151168652602081015160208701526040810151604087015260608101516060870152838101518487015260a081015160a087015260c081015160c087015273ffffffffffffffffffffffffffffffffffffffff60e08201511660e087015261010081015161010087015201516101208501526020810151610140850152604081015161016085015260608101516101808501520151910152565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc8382030161020484015287612de9565b828151910182305af15f5196604052156145bd575b50505050565b9091929394505f3d602014614896575b7fdeaddead00000000000000000000000000000000000000000000000000000000810361465957608485604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152600f60448201527f41413935206f7574206f662067617300000000000000000000000000000000006064820152fd5b92935090917fdeadaa5100000000000000000000000000000000000000000000000000000000036146bc57506146a16146966146b1925a90612ead565b608084015190612e46565b6040830151836128548295614c2a565b905b5f8080806145b7565b9061472f9060405160208501518551907ff62676f440ff169a3a9afdbf812e89e7f95975ee8e5c31214ffdef631c5f4792602073ffffffffffffffffffffffffffffffffffffffff84511693015161471261349e565b9061472260405192839283612e2c565b0390a36040525a90612ead565b61473f6080840191825190612e46565b915f905a92855161010081015161012082015148018082105f1461488e5750955b61478d73ffffffffffffffffffffffffffffffffffffffff60e08401511693518203606084015190614b09565b01925f928061485f5750505173ffffffffffffffffffffffffffffffffffffffff16935b5a900301019283026040850151928184105f14614813575050806147e6575090816147e0929361285481614c2a565b906146b3565b807f4e487b7100000000000000000000000000000000000000000000000000000000602492526021600452fd5b614848908284939795039073ffffffffffffffffffffffffffffffffffffffff165f525f60205260405f209081540180915590565b506147e6575090825f61485a93614ba9565b6147e0565b9591905161486e575b506147b1565b935090506148875a9360a05f955a900391015190614b09565b905f614868565b905095614760565b5060205f803e5f516145cd565b614a0893506149dc916148e8917e42dc5300000000000000000000000000000000000000000000000000000000602086015261020060248601526102248501916131b6565b6149ab604484018860806101a091610120815173ffffffffffffffffffffffffffffffffffffffff8151168652602081015160208701526040810151604087015260608101516060870152838101518487015260a081015160a087015260c081015160c087015273ffffffffffffffffffffffffffffffffffffffff60e08201511660e087015261010081015161010087015201516101208501526020810151610140850152604081015161016085015260608101516101808501520151910152565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc8382030161020484015284612de9565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101885287612c2d565b60205f876145a2565b5081356143a1565b73ffffffffffffffffffffffffffffffffffffffff168015614aab575f80809381935af1614a45612eba565b5015614a4d57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f41413931206661696c65642073656e6420746f2062656e6566696369617279006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4141393020696e76616c69642062656e656669636961727900000000000000006044820152fd5b90619c408201811115614b2257606491600a9103020490565b50505f90565b9190917f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f6080602083015192519473ffffffffffffffffffffffffffffffffffffffff86511694602073ffffffffffffffffffffffffffffffffffffffff60e089015116970151916040519283525f602084015260408301526060820152a4565b9060807f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f91602084015193519573ffffffffffffffffffffffffffffffffffffffff87511695602073ffffffffffffffffffffffffffffffffffffffff60e08a015116980151926040519384521515602084015260408301526060820152a4565b60208101519051907f67b4fa9642f42120bf031f3051d1824b0fe25627945b27b8a6a65d5761d5482e60208073ffffffffffffffffffffffffffffffffffffffff855116940151604051908152a3565b90600211614cca57357fffffffffffffffffffffffffffffffffffffffff000000000000000000000000167f77020000000000000000000000000000000000000000000000000000000000001490565b505f90565b60ff8114614d2e5760ff811690601f8211614d065760405191614cf3604084612c2d565b6020808452838101919036833783525290565b7fb3512b0c000000000000000000000000000000000000000000000000000000005f5260045ffd5b506040515f6002548060011c9160018216918215614e3b575b602084108314614e0e578385528492908115614dd15750600114614d72575b612e4392500382612c2d565b5060025f90815290917f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace5b818310614db5575050906020612e4392820101614d66565b6020919350806001915483858801015201910190918392614d9d565b60209250612e439491507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001682840152151560051b820101614d66565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b92607f1692614d47565b60ff8114614e695760ff811690601f8211614d065760405191614cf3604084612c2d565b506040515f6003548060011c9160018216918215614f0b575b602084108314614e0e578385528492908115614dd15750600114614eac57612e4392500382612c2d565b5060035f90815290917fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b5b818310614eef575050906020612e4392820101614d66565b6020919350806001915483858801015201910190918392614ed7565b92607f1692614e82565b8015614fae575f60408051614f2981612c11565b828152826020820152015273ffffffffffffffffffffffffffffffffffffffff81169065ffffffffffff8160a01c16908115614fa0575b60409060d01c9165ffffffffffff825191614f7a83612c11565b8583528460208401521691829101524211908115614f9757509091565b90504211159091565b65ffffffffffff9150614f60565b505f905f90565b929190915f9080614fc8575b5050505050565b83519473ffffffffffffffffffffffffffffffffffffffff86511695614fee8386614c7a565b61535f5750853b6152fa576014821061529557604085510151602060405180927f570e1a36000000000000000000000000000000000000000000000000000000008252826004830152818781615048602482018a8d6131b6565b039273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690f190811561528a57849161526b575b5073ffffffffffffffffffffffffffffffffffffffff811680156152065787036151a1573b1561513c5750601411615139577fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d91604091503573ffffffffffffffffffffffffffffffffffffffff60e06020860151955101511673ffffffffffffffffffffffffffffffffffffffff83519260601c1682526020820152a35f80808080614fc1565b80fd5b608490604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152602060448201527f4141313520696e6974436f6465206d757374206372656174652073656e6465726064820152fd5b608482604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152602060448201527f4141313420696e6974436f6465206d7573742072657475726e2073656e6465726064820152fd5b608483604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601b60448201527f4141313320696e6974436f6465206661696c6564206f72204f4f4700000000006064820152fd5b615284915060203d602011611771576117638183612c2d565b5f615091565b6040513d86823e3d90fd5b608490604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601760448201527f4141393920696e6974436f646520746f6f20736d616c6c0000000000000000006064820152fd5b608490604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601f60448201527f414131302073656e64657220616c726561647920636f6e7374727563746564006064820152fd5b945050919050601482116153735750505050565b604073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169301519082601411612a3257833b15612a32575f809461542f96604051978896879586937fc09ad0d900000000000000000000000000000000000000000000000000000000855260048501526040602485015260147fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec60448601930191016131b6565b0393f1801561545557615445575b8080806145b7565b5f61544f91612c2d565b5f61543d565b6040513d5f823e3d90fd5b615478604092959493956060835260608301906133bd565b9460208201520152565b73ffffffffffffffffffffffffffffffffffffffff165f525f60205260405f2090815481811061381d5703905560019056fea2646970667358221220a2ee7c02d47f72772240d0dfa7174d99b6049a68ccdf3d4434c3918f6bd9c1e164736f6c634300081c003360a08060405234602f57336080526104c19081610034823960805181818160d80152818161023401526102e10152f35b5f80fdfe60806040526004361015610011575f80fd5b5f3560e01c8063570e1a3614610258578063b0d691fe146101ea5763c09ad0d91461003a575f80fd5b346101e65760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101e65760043573ffffffffffffffffffffffffffffffffffffffff811681036101e65760243567ffffffffffffffff81116101e657366023820112156101e6575f916100bd83923690602481600401359101610384565b906100ff73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163314610426565b82602083519301915af11561011057005b3d61080081116101dd575b60c460405160208382010160405282815260208101925f843e7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f6040519485937f65c8fd4d0000000000000000000000000000000000000000000000000000000085525f6004860152606060248601528260648601527f4141313320454950373730322073656e64657220696e6974206661696c656400608486015260a060448601525180918160a48701528686015e5f85828601015201168101030190fd5b5061080061011b565b5f80fd5b346101e6575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101e657602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b346101e65760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101e65760043567ffffffffffffffff81116101e657366023820112156101e65780600401359067ffffffffffffffff82116101e65736602483830101116101e6575f9161030873ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163314610426565b806014116101e6576020916103455f927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec36910160388401610384565b90826024858451940192013560601c5af161037c575b60209073ffffffffffffffffffffffffffffffffffffffff60405191168152f35b505f5161035b565b92919267ffffffffffffffff82116103f957604051917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f81601f8401160116830183811067ffffffffffffffff8211176103f9576040528294818452818301116101e6578281602093845f960137010152565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b1561042d57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602060248201527f414139372073686f756c642063616c6c2066726f6d20456e747279506f696e746044820152fdfea26469706673582212206423798798d408242e814ed5c031f1afcdccad1146c1c11fab88cce1fdaa4c4a64736f6c634300081c0033";
+       7              : address constant ENTRYPOINT_0_8 = 0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108;
+       8              : address constant DETERMINISTIC_DEPLOYER = 0x4e59b44847b379578588920cA78FbF26c0B4956C;
+       9              : 
+      10              : library EntryPointLib {
+      11           14 :     function deploy() internal returns (IEntryPoint) {
+      12           14 :         (bool success,) = DETERMINISTIC_DEPLOYER.call(ENTRYPOINT_0_8_INITCODE);
+      13           14 :         require(success);
+      14           14 :         return IEntryPoint(payable(ENTRYPOINT_0_8));
+      15              :     }
+      16              : }
+        
+
+
+ + + + +
Generated by: LCOV version 2.1-1
+
+ + + diff --git a/coverage/test/utils/index-sort-f.html b/coverage/test/utils/index-sort-f.html new file mode 100644 index 00000000..7e897e71 --- /dev/null +++ b/coverage/test/utils/index-sort-f.html @@ -0,0 +1,105 @@ + + + + + + + LCOV - lcov.info - test/utils + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - test/utilsCoverageTotalHit
Test:lcov.infoLines:100.0 %44
Test Date:2025-05-22 05:44:20Functions:100.0 %11
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

File Sort by file nameLine Coverage Sort by line coverageFunction Coverage Sort by function coverage
Rate Total Hit Rate Total Hit
EntryPointLib.sol +
100.0%
+
100.0 %44100.0 %11
+
+
+ + + + +
Generated by: LCOV version 2.1-1
+
+ + + diff --git a/coverage/test/utils/index-sort-l.html b/coverage/test/utils/index-sort-l.html new file mode 100644 index 00000000..7fc9707c --- /dev/null +++ b/coverage/test/utils/index-sort-l.html @@ -0,0 +1,105 @@ + + + + + + + LCOV - lcov.info - test/utils + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - test/utilsCoverageTotalHit
Test:lcov.infoLines:100.0 %44
Test Date:2025-05-22 05:44:20Functions:100.0 %11
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

File Sort by file nameLine Coverage Sort by line coverageFunction Coverage Sort by function coverage
Rate Total Hit Rate Total Hit
EntryPointLib.sol +
100.0%
+
100.0 %44100.0 %11
+
+
+ + + + +
Generated by: LCOV version 2.1-1
+
+ + + diff --git a/coverage/test/utils/index.html b/coverage/test/utils/index.html new file mode 100644 index 00000000..6e8fe632 --- /dev/null +++ b/coverage/test/utils/index.html @@ -0,0 +1,105 @@ + + + + + + + LCOV - lcov.info - test/utils + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - test/utilsCoverageTotalHit
Test:lcov.infoLines:100.0 %44
Test Date:2025-05-22 05:44:20Functions:100.0 %11
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

File Sort by file nameLine Coverage Sort by line coverageFunction Coverage Sort by function coverage
Rate Total Hit Rate Total Hit
EntryPointLib.sol +
100.0%
+
100.0 %44100.0 %11
+
+
+ + + + +
Generated by: LCOV version 2.1-1
+
+ + + diff --git a/coverage/updown.png b/coverage/updown.png new file mode 100644 index 0000000000000000000000000000000000000000..aa56a238b3e6c435265250f9266cd1b8caba0f20 GIT binary patch literal 117 zcmeAS@N?(olHy`uVBq!ia0vp^AT}Qd8;}%R+`Ae`*?77*hG?8mPH5^{)z4*}Q$iB}huR`+ literal 0 HcmV?d00001 diff --git a/lcov.info b/lcov.info new file mode 100644 index 00000000..b7b97563 --- /dev/null +++ b/lcov.info @@ -0,0 +1,626 @@ +TN: +SF:src/Kernel.sol +DA:20,0 +FN:20,Kernel.onlyEntryPointOrSelf +FNDA:0,Kernel.onlyEntryPointOrSelf +DA:21,0 +BRDA:21,0,0,- +BRDA:21,0,1,9 +DA:25,14 +FN:25,Kernel.constructor +FNDA:14,Kernel.constructor +DA:26,14 +DA:29,14 +FN:29,Kernel._domainNameAndVersion +FNDA:14,Kernel._domainNameAndVersion +DA:30,14 +DA:31,14 +DA:41,0 +FN:41,Kernel.validateUserOp +FNDA:0,Kernel.validateUserOp +DA:47,0 +DA:48,0 +DA:50,0 +BRDA:50,1,0,- +DA:51,0 +DA:57,0 +FN:57,Kernel._processUserOp +FNDA:0,Kernel._processUserOp +DA:64,0 +DA:65,0 +DA:66,0 +BRDA:66,2,0,- +DA:67,0 +DA:68,0 +DA:70,0 +DA:72,0 +DA:73,0 +DA:74,0 +DA:76,0 +DA:77,0 +DA:80,0 +FN:80,Kernel.isValidSignature +FNDA:0,Kernel.isValidSignature +DA:83,0 +FN:83,Kernel.executeUserOp +FNDA:0,Kernel.executeUserOp +DA:84,0 +DA:87,9 +FN:87,Kernel.execute +FNDA:9,Kernel.execute +DA:88,9 +DA:91,3 +FN:91,Kernel.executeFromExecutor +FNDA:3,Kernel.executeFromExecutor +DA:92,3 +DA:95,0 +FN:95,Kernel._fallback +FNDA:0,Kernel._fallback +DA:96,0 +DA:97,0 +DA:98,0 +BRDA:98,3,0,- +DA:99,0 +DA:101,0 +DA:102,0 +BRDA:102,4,0,- +DA:103,0 +DA:106,0 +DA:107,0 +BRDA:107,5,0,- +BRDA:107,5,1,- +DA:108,0 +DA:109,0 +BRDA:109,6,0,- +DA:110,0 +DA:112,0 +BRDA:112,7,0,- +DA:113,0 +DA:115,0 +BRDA:115,8,0,- +DA:116,0 +DA:126,15 +FN:126,Kernel.installModule +FNDA:15,Kernel.installModule +DA:127,15 +DA:129,15 +DA:131,15 +DA:134,0 +FN:134,Kernel.setRoot +FNDA:0,Kernel.setRoot +DA:135,0 +DA:139,0 +FN:139,Kernel.installModule +FNDA:0,Kernel.installModule +DA:140,0 +BRDA:140,9,0,- +BRDA:140,9,1,- +DA:142,0 +BRDA:142,10,0,- +BRDA:142,10,1,- +DA:143,0 +DA:147,0 +BRDA:147,11,0,- +BRDA:147,11,1,- +DA:148,0 +DA:149,0 +DA:150,0 +DA:154,0 +FN:154,Kernel._verifyInstallSignature +FNDA:0,Kernel._verifyInstallSignature +DA:159,0 +DA:160,0 +DA:161,0 +DA:162,0 +DA:172,0 +DA:175,0 +FN:175,Kernel.fallback +FNDA:0,Kernel.fallback +DA:176,0 +FNF:15 +FNH:5 +LF:70 +LH:13 +BRF:17 +BRH:1 +end_of_record +TN: +SF:src/KernelFactory.sol +DA:10,14 +FN:10,KernelFactory.constructor +FNDA:14,KernelFactory.constructor +DA:11,14 +DA:14,15 +FN:14,KernelFactory.deploy +FNDA:15,KernelFactory.deploy +DA:15,15 +DA:16,15 +DA:17,15 +DA:20,0 +FN:20,KernelFactory.deployWithAdditionalPackage +FNDA:0,KernelFactory.deployWithAdditionalPackage +DA:21,0 +DA:22,0 +DA:24,0 +DA:25,0 +DA:26,0 +FNF:3 +FNH:2 +LF:12 +LH:6 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/Lib4337.sol +DA:24,0 +FN:24,Lib4337.chainAgnosticUserOpHash +FNDA:0,Lib4337.chainAgnosticUserOpHash +DA:25,0 +DA:26,0 +DA:27,0 +DA:32,0 +FN:32,Lib4337._hashTypedDataSansChainId +FNDA:0,Lib4337._hashTypedDataSansChainId +DA:37,0 +DA:40,0 +DA:41,0 +DA:42,0 +DA:43,0 +DA:44,0 +DA:46,0 +DA:47,0 +DA:48,0 +DA:49,0 +DA:50,0 +DA:51,0 +FNF:2 +FNH:0 +LF:17 +LH:0 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/core/ExecutionManager.sol +DA:7,12 +FN:7,ExecutionManager._execute +FNDA:12,ExecutionManager._execute +DA:8,12 +DA:9,12 +DA:10,12 +DA:11,12 +BRDA:11,0,0,9 +BRDA:11,0,1,- +DA:12,9 +DA:13,3 +BRDA:13,1,0,3 +BRDA:13,1,1,- +DA:14,3 +DA:16,0 +DA:19,12 +DA:20,12 +BRDA:20,2,0,4 +BRDA:20,2,1,- +DA:21,4 +DA:22,8 +BRDA:22,3,0,4 +BRDA:22,3,1,- +DA:23,4 +DA:24,4 +BRDA:24,4,0,4 +BRDA:24,4,1,- +DA:25,4 +DA:27,0 +DA:29,12 +DA:32,4 +FN:32,ExecutionManager._executeCall +FNDA:4,ExecutionManager._executeCall +DA:33,4 +DA:34,4 +DA:35,4 +BRDA:35,5,0,2 +DA:36,2 +DA:40,4 +FN:40,ExecutionManager._executeDelegateCall +FNDA:4,ExecutionManager._executeDelegateCall +DA:41,4 +DA:42,4 +DA:43,4 +BRDA:43,6,0,2 +DA:44,2 +DA:48,4 +FN:48,ExecutionManager._executeBatchCall +FNDA:4,ExecutionManager._executeBatchCall +DA:49,4 +DA:50,4 +DA:51,4 +DA:53,4 +DA:54,8 +DA:55,8 +DA:56,8 +BRDA:56,7,0,2 +DA:57,2 +DA:63,3 +FN:63,ExecutionManager._onRevertThrow +FNDA:3,ExecutionManager._onRevertThrow +DA:66,3 +DA:67,3 +DA:71,3 +FN:71,ExecutionManager._onRevertSilent +FNDA:3,ExecutionManager._onRevertSilent +DA:74,12 +FN:74,ExecutionManager._call +FNDA:12,ExecutionManager._call +DA:77,12 +DA:78,12 +DA:79,12 +DA:83,4 +FN:83,ExecutionManager._delegateCall +FNDA:4,ExecutionManager._delegateCall +DA:86,4 +DA:87,4 +DA:89,4 +FNF:8 +FNH:8 +LF:49 +LH:47 +BRF:13 +BRH:8 +end_of_record +TN: +SF:src/core/ExecutorManager.sol +DA:17,17 +FN:17,ExecutorManager._executorStorage +FNDA:17,ExecutorManager._executorStorage +DA:19,17 +DA:23,0 +FN:23,ExecutorManager.executorConfig +FNDA:0,ExecutorManager.executorConfig +DA:24,0 +DA:27,17 +FN:27,ExecutorManager._executorConfig +FNDA:17,ExecutorManager._executorConfig +DA:28,17 +DA:31,14 +FN:31,ExecutorManager._installExecutor +FNDA:14,ExecutorManager._installExecutor +DA:33,14 +DA:34,14 +BRDA:34,0,0,14 +DA:35,14 +DA:37,14 +DA:40,0 +FN:40,ExecutorManager._uninstallExecutor +FNDA:0,ExecutorManager._uninstallExecutor +DA:41,0 +FNF:5 +FNH:3 +LF:13 +LH:9 +BRF:1 +BRH:1 +end_of_record +TN: +SF:src/core/HookManager.sol +DA:14,0 +FN:14,HookManager._installHook +FNDA:0,HookManager._installHook +DA:15,0 +BRDA:15,0,0,- +DA:16,0 +BRDA:16,1,0,- +BRDA:16,1,1,- +DA:20,0 +FN:20,HookManager._uninstallHook +FNDA:0,HookManager._uninstallHook +DA:24,3 +FN:24,HookManager._preHook +FNDA:3,HookManager._preHook +DA:25,3 +BRDA:25,2,0,- +BRDA:25,2,1,3 +DA:26,3 +BRDA:26,3,0,- +DA:27,0 +DA:30,3 +FN:30,HookManager._postHook +FNDA:3,HookManager._postHook +DA:33,3 +BRDA:33,4,0,- +DA:34,0 +FNF:4 +FNH:2 +LF:11 +LH:5 +BRF:7 +BRH:1 +end_of_record +TN: +SF:src/core/ModuleManager.sol +DA:24,3 +FN:24,ModuleManager.onlyExecutor +FNDA:3,ModuleManager.onlyExecutor +DA:25,3 +DA:26,3 +DA:28,3 +DA:31,0 +FN:31,ModuleManager._initialized +FNDA:0,ModuleManager._initialized +DA:32,0 +DA:35,0 +FN:35,ModuleManager._installHash +FNDA:0,ModuleManager._installHash +DA:36,0 +DA:37,0 +DA:38,0 +DA:39,0 +DA:43,0 +DA:46,15 +FN:46,ModuleManager._installModule +FNDA:15,ModuleManager._installModule +DA:49,15 +DA:50,15 +BRDA:50,0,0,1 +BRDA:50,0,1,- +DA:51,1 +DA:52,14 +BRDA:52,1,0,14 +BRDA:52,1,1,- +DA:53,14 +DA:54,0 +BRDA:54,2,0,- +BRDA:54,2,1,- +DA:55,0 +DA:56,0 +BRDA:56,3,0,- +BRDA:56,3,1,- +DA:57,0 +DA:58,0 +BRDA:58,4,0,- +BRDA:58,4,1,- +DA:59,0 +DA:60,0 +BRDA:60,5,0,- +BRDA:60,5,1,- +DA:61,0 +DA:63,0 +DA:65,15 +DA:66,15 +DA:69,0 +FN:69,ModuleManager._install +FNDA:0,ModuleManager._install +DA:70,0 +DA:71,0 +DA:72,0 +DA:76,15 +FN:76,ModuleManager._install +FNDA:15,ModuleManager._install +DA:82,15 +DA:83,15 +DA:86,0 +FN:86,ModuleManager._uninstall +FNDA:0,ModuleManager._uninstall +DA:93,0 +DA:94,0 +FNF:7 +FNH:3 +LF:39 +LH:15 +BRF:12 +BRH:2 +end_of_record +TN: +SF:src/core/SelectorManager.sol +DA:26,0 +FN:26,SelectorManager.selectorConfig +FNDA:0,SelectorManager.selectorConfig +DA:27,0 +DA:30,0 +FN:30,SelectorManager._selectorConfig +FNDA:0,SelectorManager._selectorConfig +DA:31,0 +DA:34,0 +FN:34,SelectorManager._selectorStorage +FNDA:0,SelectorManager._selectorStorage +DA:35,0 +DA:37,0 +DA:41,0 +FN:41,SelectorManager._installSelector +FNDA:0,SelectorManager._installSelector +DA:42,0 +DA:43,0 +BRDA:43,0,0,- +BRDA:43,0,1,- +DA:44,0 +DA:45,0 +DA:46,0 +DA:47,0 +DA:48,0 +DA:49,0 +FNF:4 +FNH:0 +LF:16 +LH:0 +BRF:2 +BRH:0 +end_of_record +TN: +SF:src/core/ValidationManager.sol +DA:44,1 +FN:44,ValidationManager._validationStorage +FNDA:1,ValidationManager._validationStorage +DA:46,1 +DA:50,1 +FN:50,ValidationManager._installValidator +FNDA:1,ValidationManager._installValidator +DA:51,1 +BRDA:51,0,0,- +BRDA:51,0,1,1 +DA:52,1 +DA:53,1 +DA:56,0 +FN:56,ValidationManager._uninstallValidator +FNDA:0,ValidationManager._uninstallValidator +DA:59,0 +DA:60,0 +DA:63,0 +FN:63,ValidationManager._installPolicy +FNDA:0,ValidationManager._installPolicy +DA:64,0 +BRDA:64,1,0,- +BRDA:64,1,1,- +DA:65,0 +DA:66,0 +DA:67,0 +BRDA:67,2,0,- +BRDA:67,2,1,- +DA:68,0 +BRDA:68,3,0,- +BRDA:68,3,1,- +DA:69,0 +DA:70,0 +DA:72,0 +BRDA:72,4,0,- +BRDA:72,4,1,- +DA:74,0 +DA:77,0 +FN:77,ValidationManager._uninstallPolicy +FNDA:0,ValidationManager._uninstallPolicy +DA:80,0 +FN:80,ValidationManager._installSigner +FNDA:0,ValidationManager._installSigner +DA:81,0 +BRDA:81,5,0,- +BRDA:81,5,1,- +DA:82,0 +DA:83,0 +DA:84,0 +BRDA:84,6,0,- +BRDA:84,6,1,- +DA:85,0 +BRDA:85,7,0,- +BRDA:85,7,1,- +DA:86,0 +BRDA:86,8,0,- +BRDA:86,8,1,- +DA:87,0 +DA:88,0 +DA:90,0 +BRDA:90,9,0,- +BRDA:90,9,1,- +DA:92,0 +DA:94,0 +DA:97,0 +FN:97,ValidationManager._uninstallSigner +FNDA:0,ValidationManager._uninstallSigner +DA:100,0 +FN:100,ValidationManager._checkValidation +FNDA:0,ValidationManager._checkValidation +DA:101,0 +DA:102,0 +DA:103,0 +BRDA:103,10,0,- +BRDA:103,10,1,- +DA:104,0 +DA:106,0 +DA:107,0 +BRDA:107,11,0,- +BRDA:107,11,1,- +DA:111,0 +FN:111,ValidationManager._parseNonce +FNDA:0,ValidationManager._parseNonce +DA:120,0 +DA:121,0 +DA:122,0 +DA:126,0 +FN:126,ValidationManager._verifySignature +FNDA:0,ValidationManager._verifySignature +DA:131,0 +BRDA:131,12,0,- +DA:132,0 +DA:134,0 +DA:135,0 +DA:138,0 +FN:138,ValidationManager._validateUserOp +FNDA:0,ValidationManager._validateUserOp +DA:139,0 +BRDA:139,13,0,- +DA:140,0 +DA:144,0 +FN:144,ValidationManager._verify7702Signature +FNDA:0,ValidationManager._verify7702Signature +DA:145,0 +DA:148,0 +FN:148,ValidationManager._setRoot +FNDA:0,ValidationManager._setRoot +DA:149,0 +DA:150,0 +BRDA:150,14,0,- +BRDA:150,14,1,- +DA:151,0 +DA:152,0 +BRDA:152,15,0,- +BRDA:152,15,1,- +DA:153,0 +DA:155,0 +DA:157,0 +DA:160,0 +FN:160,ValidationManager._setRoot +FNDA:0,ValidationManager._setRoot +DA:161,0 +DA:162,0 +FNF:14 +FNH:2 +LF:65 +LH:6 +BRF:30 +BRH:1 +end_of_record +TN: +SF:test/Kernel.t.sol +DA:14,1 +FN:14,MockValidator.onInstall +FNDA:1,MockValidator.onInstall +DA:15,1 +DA:18,0 +FN:18,MockValidator.onUninstall +FNDA:0,MockValidator.onUninstall +DA:19,0 +DA:28,8 +FN:28,MockCallee.foo +FNDA:8,MockCallee.foo +DA:29,8 +DA:30,8 +DA:33,2 +FN:33,MockCallee.lorem +FNDA:2,MockCallee.lorem +DA:34,2 +DA:37,6 +FN:37,MockCallee.forceRevert +FNDA:6,MockCallee.forceRevert +DA:38,6 +FNF:5 +FNH:4 +LF:11 +LH:9 +BRF:0 +BRH:0 +end_of_record +TN: +SF:test/utils/EntryPointLib.sol +DA:11,14 +FN:11,EntryPointLib.deploy +FNDA:14,EntryPointLib.deploy +DA:12,14 +DA:13,14 +BRDA:13,0,0,- +BRDA:13,0,1,14 +DA:14,14 +FNF:1 +FNH:1 +LF:4 +LH:4 +BRF:2 +BRH:1 +end_of_record diff --git a/src/Kernel.sol b/src/Kernel.sol index 7c085b00..80844e23 100644 --- a/src/Kernel.sol +++ b/src/Kernel.sol @@ -17,8 +17,8 @@ contract Kernel is ModuleManager, ExecutionManager, EIP712 { error Unauthorized(); - modifier onlyEntryPoint() { - require(msg.sender == address(entryPoint), Unauthorized()); + modifier onlyEntryPointOrSelf() { + require(msg.sender == address(entryPoint) || msg.sender == address(this), Unauthorized()); _; } @@ -41,11 +41,17 @@ contract Kernel is ModuleManager, ExecutionManager, EIP712 { function validateUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash, uint256 missingAccountFunds) external payable - onlyEntryPoint + onlyEntryPointOrSelf returns (uint256 validationData) { (ValidationId verifier, bytes32 opHash, bytes calldata userOpSignature) = _processUserOp(userOp, userOpHash); - return _verifySignature(verifier, opHash, userOpSignature); + validationData = _validateUserOp(verifier, opHash, userOp, userOpSignature); + assembly { + if missingAccountFunds { + pop(call(gas(), caller(), missingAccountFunds, callvalue(), callvalue(), callvalue(), callvalue())) + //ignore failure (its EntryPoint's job to verify, not account.) + } + } } function _processUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash) @@ -56,7 +62,6 @@ contract Kernel is ModuleManager, ExecutionManager, EIP712 { userOp.nonce = vMode | vType | vId */ (ValidationMode vMode, ValidationType vType, ValidationId vId) = _parseNonce(userOp.nonce); - _checkValidation(vMode, vType, vId); signature = userOp.signature; if (isEnable(vMode)) { bool enableReplayable = isEnableReplayable(vMode); @@ -64,27 +69,53 @@ contract Kernel is ModuleManager, ExecutionManager, EIP712 { assembly { sig := signature.offset } - signature = sig.userOpSignature; _verifyInstallSignature(enableReplayable, sig.packages, sig.enableSignature); _install(sig.packages); + signature = sig.userOpSignature; } + _checkValidation(vMode, vType, vId); opHash = isReplayable(vMode) ? Lib4337.chainAgnosticUserOpHash(msg.sender, userOp) : userOpHash; } function isValidSignature(bytes32 hash, bytes calldata signature) external view returns (bytes4) {} /// execution - function executeUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash) external payable onlyEntryPoint { + function executeUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash) external payable onlyEntryPointOrSelf { (bool success, bytes memory ret) = address(this).delegatecall(userOp.callData[4:]); } - function execute(bytes32 mode, bytes calldata executionData) external payable { + function execute(bytes32 mode, bytes calldata executionData) external payable onlyEntryPointOrSelf { _execute(mode, executionData); } - function executeFromExecutor(bytes32 mode, bytes calldata executionData) external payable { + function executeFromExecutor(bytes32 mode, bytes calldata executionData) external payable onlyExecutor { _execute(mode, executionData); } + + function _fallback() internal { + bytes4 selector = bytes4(msg.data); + SelectorConfig storage $ = _selectorConfig(selector); + if($.target == address(0)) { + revert InvalidSelector(); + } + bytes memory hookData; + if(address($.hook) != address(0)) { + hookData = _preHook($.hook); + } + + bool success; + if($.callType == CallType.wrap(bytes1(0x00))) { + success = _call($.target, 0, msg.data); + } else if($.callType == CallType.wrap(bytes1(0xff))) { + success = _delegateCall($.target, msg.data); + } + if(!success) { + _onRevertThrow(); + } + if(address($.hook) != address(0)) { + _postHook($.hook, hookData); + } + } /// management struct InstallModuleDataFormat { @@ -92,19 +123,32 @@ contract Kernel is ModuleManager, ExecutionManager, EIP712 { bytes internalData; } - function installModule(uint256 moduleType, address module, bytes calldata initData) external payable { + function installModule(uint256 moduleType, address module, bytes calldata initData) external payable onlyEntryPointOrSelf { InstallModuleDataFormat calldata imdf; assembly { imdf := initData.offset } - _installModule(moduleType, module, imdf.installData, imdf.internalData); } - // NOTE : this ONLY allows root signature + function setRoot(ValidationId vId) external payable onlyEntryPointOrSelf { + _setRoot(vId); + } + + // NOTE : this ONLY allows root signature, for now function installModule(bool replayable, Install[] calldata packages, bytes calldata signature) external { - require(_verifyInstallSignature(replayable, packages, signature), InstallSignatureVerificationFailed()); - _install(packages); + if(_initialized()) { + // if 7702 or already initialized, use root signature to install module + require(_verifyInstallSignature(replayable, packages, signature), InstallSignatureVerificationFailed()); + _install(packages); + } else { + // this is initialize + // require first package to be the root validator + require(packages.length > 0); + Install calldata root = packages[0]; + _install(packages); + _setRoot(root); + } } function _verifyInstallSignature(bool replayable, Install[] calldata packages, bytes calldata signature) @@ -112,7 +156,7 @@ contract Kernel is ModuleManager, ExecutionManager, EIP712 { view returns (bool success) { - ValidationId vId = _validationStorage().rootValidator; + ValidationId vId = _validationStorage().root; function(bytes32) internal view returns(bytes32) hashTypedData = replayable ? _hashTypedDataSansChainId : _hashTypedData; bytes32 digest = hashTypedData( @@ -125,6 +169,10 @@ contract Kernel is ModuleManager, ExecutionManager, EIP712 { ) ) ); - _verifySignature(vId, digest, signature); + _verifySignature(vId, address(this), digest, signature); + } + + fallback() external payable { + _fallback(); } } diff --git a/src/KernelFactory.sol b/src/KernelFactory.sol index 4c811dfc..2d742bc3 100644 --- a/src/KernelFactory.sol +++ b/src/KernelFactory.sol @@ -1,6 +1,6 @@ pragma solidity ^0.8.0; -import {Kernel} from "./Kernel.sol"; +import {Kernel, Install} from "./Kernel.sol"; import {LibClone} from "solady/utils/LibClone.sol"; import {IEntryPoint} from "account-abstraction/interfaces/IEntryPoint.sol"; @@ -17,5 +17,12 @@ contract KernelFactory { return Kernel(payable(account)); } - function deployWithSignature(bytes calldata initData, bytes calldata signature) external payable returns (Kernel) {} + function deployWithAdditionalPackage(bytes calldata initData, bool replayable, Install[] calldata packages, bytes calldata signature) external payable returns (Kernel) { + bytes32 salt = keccak256(initData); + (bool deployed, address account) = LibClone.createDeterministicERC1967(msg.value, address(template), salt); + + Kernel k = Kernel(payable(account)); + k.installModule(replayable, packages, signature); + return k; + } } diff --git a/src/core/ExecutionManager.sol b/src/core/ExecutionManager.sol index 8ddb389f..ee3d174d 100644 --- a/src/core/ExecutionManager.sol +++ b/src/core/ExecutionManager.sol @@ -1,14 +1,13 @@ pragma solidity ^0.8.0; import {LibERC7579} from "solady/accounts/LibERC7579.sol"; +import "../types/Error.sol"; -contract ExecutionManager { - error NotSupportedCallType(); - error NotSupportedExecType(); +abstract contract ExecutionManager { function _execute(bytes32 mode, bytes calldata executionData) internal { bytes1 callType = LibERC7579.getCallType(mode); bytes1 execType = LibERC7579.getExecType(mode); - function(bytes memory) onRevert; + function() onRevert; if(execType == LibERC7579.EXECTYPE_DEFAULT) { onRevert = _onRevertThrow; } else if(execType == LibERC7579.EXECTYPE_TRY) { @@ -17,83 +16,77 @@ contract ExecutionManager { revert NotSupportedExecType(); } - function(bytes calldata, function(bytes memory)) executeFunction; + function(bytes calldata, function()) executeFunction; if(callType == LibERC7579.CALLTYPE_SINGLE) { executeFunction = _executeCall; } else if(callType == LibERC7579.CALLTYPE_BATCH) { executeFunction = _executeBatchCall; } else if(callType == LibERC7579.CALLTYPE_DELEGATECALL) { executeFunction = _executeDelegateCall; -// } else if(callType == LibERC7579.CALLTYPE_STATICCALL) { TODO: let's deal with static call later -// executeFunction = _executeStaticCall; } else { revert NotSupportedCallType(); } + executeFunction(executionData, onRevert); } - function _executeCall(bytes calldata executionData, function(bytes memory) onRevert) internal { + function _executeCall(bytes calldata executionData, function() onRevert) internal { (address target, uint256 value, bytes calldata data) = LibERC7579.decodeSingle(executionData); - (bool success, bytes memory res) = _call(target, value, data); + bool success = _call(target, value, data); if(!success) { - onRevert(res); + onRevert(); } } - function _executeDelegateCall(bytes calldata executionData, function(bytes memory) onRevert) internal { + function _executeDelegateCall(bytes calldata executionData, function() onRevert) internal { (address delegate, bytes calldata data) = LibERC7579.decodeDelegate(executionData); - (bool success, bytes memory res) = _delegateCall(delegate, data); + bool success = _delegateCall(delegate, data); if(!success) { - onRevert(res); + onRevert(); } } - function _executeBatchCall(bytes calldata executionData, function(bytes memory) onRevert) internal { + function _executeBatchCall(bytes calldata executionData, function() onRevert) internal { bytes32[] calldata pointers = LibERC7579.decodeBatch(executionData); uint256 length = pointers.length; bytes[] memory result = new bytes[](length); unchecked { for (uint256 i; i < length; i++) { (address target, uint256 value, bytes calldata data) = LibERC7579.getExecution(pointers, i); - (bool success, bytes memory ret) = _call(target, value, data); - onRevert(ret); + bool success = _call(target, value, data); + if(!success) { + onRevert(); + } } } } - function _onRevertThrow(bytes memory revertData) internal { - uint256 length = revertData.length; + function _onRevertThrow() internal { assembly { - revert(revertData, length) + // Bubble up the revert if the call reverts. + returndatacopy(0x00, 0x00, returndatasize()) + revert(0x00, returndatasize()) } } - function _onRevertSilent(bytes memory revertData) internal { + function _onRevertSilent() internal { } - function _call(address target, uint256 value, bytes calldata callData) internal returns(bool success, bytes memory result){ + function _call(address target, uint256 value, bytes calldata callData) internal returns(bool success){ /// @solidity memory-safe-assembly assembly { - result := mload(0x40) - calldatacopy(result, callData.offset, callData.length) - success := call(gas(), target, value, result, callData.length, codesize(), 0x00) - mstore(result, returndatasize()) // Store the length. - let o := add(result, 0x20) - returndatacopy(o, 0x00, returndatasize()) // Copy the returndata. - mstore(0x40, add(o, returndatasize())) // Allocate the memory. + let ptr := mload(0x40) + calldatacopy(ptr, callData.offset, callData.length) + success := call(gas(), target, value, ptr, callData.length, codesize(), 0x00) } } - function _delegateCall(address delegate, bytes calldata callData) internal returns(bool success, bytes memory result){ + function _delegateCall(address delegate, bytes calldata callData) internal returns(bool success){ /// @solidity memory-safe-assembly assembly { - result := mload(0x40) - calldatacopy(result, callData.offset, callData.length) + let ptr := mload(0x40) + calldatacopy(ptr, callData.offset, callData.length) // Forwards the `data` to `delegate` via delegatecall. - success := delegatecall(gas(), delegate, result, callData.length, codesize(), 0x00) - mstore(result, returndatasize()) // Store the length. - let o := add(result, 0x20) - returndatacopy(o, 0x00, returndatasize()) // Copy the returndata. - mstore(0x40, add(o, returndatasize())) // Allocate the memory. + success := delegatecall(gas(), delegate, ptr, callData.length, codesize(), 0x00) } } } diff --git a/src/core/ExecutorManager.sol b/src/core/ExecutorManager.sol new file mode 100644 index 00000000..2d7e0a31 --- /dev/null +++ b/src/core/ExecutorManager.sol @@ -0,0 +1,43 @@ +pragma solidity ^0.8.0; + +import "../types/Types.sol"; +import "../types/Constants.sol"; +import "../interfaces/IERC7579Modules.sol"; + +contract ExecutorManager { + error NotExecutor(); + struct ExecutorConfig { + IHook hook; // address(1) : hook not required, address(0) : validator not installed + } + + struct ExecutorStorage { + mapping(IExecutor => ExecutorConfig) executorConfig; + } + + function _executorStorage() internal view returns (ExecutorStorage storage $) { + assembly { + $.slot := EXECUTOR_MANAGER_STORAGE_SLOT + } + } + + function executorConfig(IExecutor executor) external view returns (ExecutorConfig memory) { + return _executorConfig(executor); + } + + function _executorConfig(IExecutor executor) internal view returns (ExecutorConfig storage config) { + config = _executorStorage().executorConfig[executor]; + } + + function _installExecutor(address _executor, bytes calldata _internalData, bool _installSuccess) internal { + // NOTE: we don't care if install was successful + address hook = _internalData.length >= 20 ? address(bytes20(_internalData[0:20])) : address(0); + if(hook == address(0)) { + hook = address(1); // address(1) indicates it is installed and does not require any hook + } + _executorConfig(IExecutor(_executor)).hook = IHook(hook); + } + + function _uninstallExecutor(address _executor, bytes calldata _internalData, bool _installSuccess) internal { + _executorConfig(IExecutor(_executor)).hook = IHook(address(0)); + } +} diff --git a/src/core/HookManager.sol b/src/core/HookManager.sol new file mode 100644 index 00000000..8343069c --- /dev/null +++ b/src/core/HookManager.sol @@ -0,0 +1,37 @@ +pragma solidity ^0.8.0; + +import {IHook, IFallback, IModule} from "../interfaces/IERC7579Modules.sol"; +import {CallType} from "../types/Types.sol"; +import { + SELECTOR_MANAGER_STORAGE_SLOT, + CALLTYPE_DELEGATECALL, + CALLTYPE_SINGLE, + MODULE_TYPE_FALLBACK +} from "../types/Constants.sol"; +import "../types/Error.sol"; + +abstract contract HookManager { + function _installHook(address _hook, bytes calldata _internalData, bool _installSuccess) internal { + if(_internalData.length == 0) { + require(_installSuccess, ModuleInstallFailed()); + } + } + + function _uninstallHook(address _hook, bytes calldata _internalData, bool _uninstallSuccess) internal { + // no-op + } + + function _preHook(IHook _hook) internal returns(bytes memory context){ + require(address(_hook) != address(0), NotInstalled()); + if(address(_hook) != address(1)) { + context = _hook.preCheck(msg.sender, msg.value, msg.data); + } + } + function _postHook(IHook _hook, bytes memory context) internal { + // bool success, + // bytes memory result + if(address(_hook) != address(1)) { + _hook.postCheck(context); + } + } +} diff --git a/src/core/ModuleManager.sol b/src/core/ModuleManager.sol index 985fd409..d56e5827 100644 --- a/src/core/ModuleManager.sol +++ b/src/core/ModuleManager.sol @@ -2,21 +2,14 @@ pragma solidity ^0.8.0; import "../interfaces/IERC7579Modules.sol"; import {ValidationManager} from "./ValidationManager.sol"; +import {ExecutorManager} from "./ExecutorManager.sol"; +import {HookManager} from "./HookManager.sol"; +import {SelectorManager} from "./SelectorManager.sol"; import "../types/Error.sol"; import "../types/Events.sol"; +import "../types/Structs.sol"; +import "../types/Types.sol"; -struct Install { - uint256 moduleType; - address module; - bytes moduleData; - bytes internalData; -} - -struct Uninstall { - uint256 moduleType; - address module; - bytes data; -} function calldataKeccak(bytes calldata data) pure returns (bytes32 ret) { assembly ("memory-safe") { @@ -27,7 +20,18 @@ function calldataKeccak(bytes calldata data) pure returns (bytes32 ret) { } } -contract ModuleManager is ValidationManager { +contract ModuleManager is ValidationManager, ExecutorManager, HookManager, SelectorManager { + modifier onlyExecutor { + IHook hook = _executorConfig(IExecutor(msg.sender)).hook; + bytes memory hookData = _preHook(hook); + _; + _postHook(hook, hookData); + } + + function _initialized() internal view returns(bool) { + return bytes3(address(this).code) == bytes3(0xef0100) || ValidationId.unwrap(_validationStorage().root) != bytes20(0); + } + function _installHash(Install[] calldata packages) internal pure returns (bytes32) { bytes32[] memory packageHashes = new bytes32[](packages.length); for (uint256 i = 0; i < packages.length; i++) { @@ -44,7 +48,17 @@ contract ModuleManager is ValidationManager { { function(address, bytes calldata, bool) hook; if (moduleType == 1) { - hook = _installValidatorHook; + hook = _installValidator; + } else if(moduleType == 2) { + hook = _installExecutor; + } else if(moduleType == 3) { + hook = _installSelector; + } else if(moduleType == 4) { + hook = _installHook; + } else if(moduleType == 5) { + hook = _installPolicy; + } else if(moduleType == 6) { + hook = _installSigner; } else { revert NotImplemented(); } @@ -79,4 +93,5 @@ contract ModuleManager is ValidationManager { (bool success,) = module.call(abi.encodeWithSelector(IModule.onUninstall.selector, data)); hook(module, internalData, success); } + } diff --git a/src/core/SelectorManager.sol b/src/core/SelectorManager.sol new file mode 100644 index 00000000..7317edf0 --- /dev/null +++ b/src/core/SelectorManager.sol @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {IHook, IFallback, IModule} from "../interfaces/IERC7579Modules.sol"; +import {CallType} from "../types/Types.sol"; +import { + SELECTOR_MANAGER_STORAGE_SLOT, + CALLTYPE_DELEGATECALL, + CALLTYPE_SINGLE, + MODULE_TYPE_FALLBACK +} from "../types/Constants.sol"; +import "../types/Error.sol"; + +abstract contract SelectorManager { + + struct SelectorConfig { + IHook hook; // 20 bytes for hook address + address target; // 20 bytes target will be fallback module, called with call + CallType callType; + } + + struct SelectorStorage { + mapping(bytes4 => SelectorConfig) selectorConfig; + } + + function selectorConfig(bytes4 selector) external view returns (SelectorConfig memory) { + return _selectorConfig(selector); + } + + function _selectorConfig(bytes4 selector) internal view returns (SelectorConfig storage config) { + config = _selectorStorage().selectorConfig[selector]; + } + + function _selectorStorage() internal pure returns (SelectorStorage storage ss) { + bytes32 slot = SELECTOR_MANAGER_STORAGE_SLOT; + assembly { + ss.slot := slot + } + } + + function _installSelector(address _module, bytes calldata _internalData, bool _installSuccess) internal { + CallType callType = CallType.wrap(bytes1(_internalData[4])); + require(callType == CALLTYPE_DELEGATECALL || _installSuccess, ModuleInstallFailed()); + bytes4 selector = bytes4(_internalData[0:4]); + address hook = address(bytes20(_internalData[5:25])); + SelectorConfig storage $ = _selectorConfig(selector); + $.target = _module; + $.callType = callType; + $.hook = IHook(hook); + } +} diff --git a/src/core/ValidationManager.sol b/src/core/ValidationManager.sol index b52ffa16..0cf26eb2 100644 --- a/src/core/ValidationManager.sol +++ b/src/core/ValidationManager.sol @@ -5,9 +5,13 @@ import "../interfaces/IERC7579Modules.sol"; import "../types/Error.sol"; import "../types/Types.sol"; import "../types/Constants.sol"; +import "../types/Structs.sol"; +import {ECDSA} from "solady/utils/ECDSA.sol"; struct ValidationInfo { - bool enabled; + ValidationType vType; + address[] policies; + address signer; bytes4 group; } @@ -17,8 +21,8 @@ struct ValidationGroupInfo { } struct ValidationStorage { - ValidationId rootValidator; - mapping(IValidator validator => ValidationInfo) vInfo; + ValidationId root; + mapping(ValidationId vId => ValidationInfo) vInfo; mapping(bytes4 group => ValidationGroupInfo) gInfo; } @@ -34,37 +38,74 @@ function getType(ValidationId validator) pure returns (ValidationType vType) { } } -contract ValidationManager { +abstract contract ValidationManager { + ValidationId transient installingPermission; + function _validationStorage() internal view returns (ValidationStorage storage $) { assembly { $.slot := VALIDATION_MANAGER_STORAGE_SLOT } } - function _installValidatorHook(address _validator, bytes calldata _internalData, bool _installSuccess) internal { + function _installValidator(address _validator, bytes calldata _internalData, bool _installSuccess) internal { require(_installSuccess, ModuleInstallFailed()); ValidationStorage storage $ = _validationStorage(); - $.vInfo[IValidator(_validator)].enabled = true; + $.vInfo[ValidationId.wrap(bytes20(_validator))].vType = VALIDATION_TYPE_VALIDATOR; } - function _uninstallValidatorHook(address _validator, bytes calldata _internalData, bool _uninstallSuccess) + function _uninstallValidator(address _validator, bytes calldata _internalData, bool _uninstallSuccess) internal { - require(_uninstallSuccess, ModuleUninstallFailed()); ValidationStorage storage $ = _validationStorage(); - $.vInfo[IValidator(_validator)].enabled = false; + $.vInfo[ValidationId.wrap(bytes20(_validator))].vType = VALIDATION_TYPE_VALIDATOR; + } + + function _installPolicy(address _policy, bytes calldata _internalData, bool _installSuccess) internal { + require(_installSuccess, ModuleInstallFailed()); + ValidationStorage storage $ = _validationStorage(); + ValidationId vId = ValidationId.wrap(bytes20(_internalData[0:20])); + if(installingPermission == ValidationId.wrap(bytes20(0))) { + require(vId != ValidationId.wrap(bytes20(0)), "invalid validationId"); + installingPermission = ValidationId.wrap(bytes20(_internalData[0:20])); + $.vInfo[vId].vType = VALIDATION_TYPE_PERMISSION; + } else { + require(installingPermission == vId, "permissionId should be consistent"); + } + $.vInfo[vId].policies.push(_policy); + } + + function _uninstallPolicy(address _policy, bytes calldata _internalData, bool _uninstallSuccess) internal { + } + + function _installSigner(address _signer, bytes calldata _internalData, bool _installSuccess) internal { + require(_installSuccess, ModuleInstallFailed()); + ValidationStorage storage $ = _validationStorage(); + ValidationId vId = ValidationId.wrap(bytes20(_internalData[0:20])); + if(installingPermission == ValidationId.wrap(bytes20(0))) { + require(vId != ValidationId.wrap(bytes20(0)), "invalid validationId"); + require($.vInfo[vId].vType == ValidationType.wrap(0x00), "already taken"); + installingPermission = ValidationId.wrap(bytes20(_internalData[0:20])); + $.vInfo[vId].vType = VALIDATION_TYPE_PERMISSION; + } else { + require(installingPermission == vId, "permissionId should be consistent"); + } + $.vInfo[vId].signer = _signer; + + installingPermission = ValidationId.wrap(bytes20(0)); + } + + function _uninstallSigner(address _signer, bytes calldata _internalData, bool _uninstallSuccess) internal { } function _checkValidation(ValidationMode vMode, ValidationType vType, ValidationId vId) internal view { ValidationStorage storage $ = _validationStorage(); ValidationId v; if (vType == VALIDATION_TYPE_ROOT) { - v = $.rootValidator; + v = $.root; } else { v = vId; - require($.vInfo[IValidator(getValidator(v))].enabled, InvalidValidator()); + require($.vInfo[vId].vType == vType, InvalidValidator()); } - // TODO : add permission support } function _parseNonce(uint256 nonce) @@ -82,12 +123,42 @@ contract ValidationManager { } } - function _verifySignature(ValidationId vId, bytes32 _hash, bytes calldata _signature) + function _verifySignature(ValidationId vId, address requester, bytes32 _hash, bytes calldata _signature) internal view returns (uint256 validationData) { + if(ValidationId.unwrap(vId) == bytes20(0)) { + return _verify7702Signature(_hash, _signature) ? 0 : 1; + } IValidator validator = IValidator(getValidator(vId)); // TODO: add permission support; - validator.isValidSignatureWithSender(address(0), /*NOTE: fix this */ _hash, _signature); + validator.isValidSignatureWithSender(requester, /*NOTE: fix this */ _hash, _signature); + } + + function _validateUserOp(ValidationId vId, bytes32 opHash, PackedUserOperation calldata op, bytes calldata userOpSignature) internal returns(uint256 validationData) { + if(ValidationId.unwrap(vId) == bytes20(0)) { + return _verify7702Signature(opHash, userOpSignature) ? 0 : 1; + } + } + + function _verify7702Signature(bytes32 hash, bytes calldata sig) internal view returns (bool) { + return ECDSA.recover(hash, sig) == address(this); + } + + function _setRoot(Install calldata pkg) internal { + ValidationId vId; + if(pkg.moduleType == 1) { + vId = ValidationId.wrap(bytes20(pkg.module)); + } else if (pkg.moduleType == 5 || pkg.moduleType == 6) { + vId = ValidationId.wrap(bytes20(pkg.internalData[0:4])); + } else { + revert InvalidRootValidation(); + } + _setRoot(vId); + } + + function _setRoot(ValidationId vId) internal { + ValidationStorage storage $ = _validationStorage(); + $.root = vId; } } diff --git a/src/types/Constants.sol b/src/types/Constants.sol index 7c682aec..f40c83de 100644 --- a/src/types/Constants.sol +++ b/src/types/Constants.sol @@ -2,8 +2,33 @@ pragma solidity ^0.8.0; import "./Types.sol"; -// TODO: change this -- recalculate -bytes32 constant VALIDATION_MANAGER_STORAGE_SLOT = 0x7bcaa2ced2a71450ed5a9a1b4848e8e5206dbc3f06011e595f7f55428cc6f84f; +// Default CallType +CallType constant CALLTYPE_SINGLE = CallType.wrap(0x00); +// Batched CallType +CallType constant CALLTYPE_BATCH = CallType.wrap(0x01); +CallType constant CALLTYPE_STATIC = CallType.wrap(0xFE); +// @dev Implementing delegatecall is OPTIONAL! +// implement delegatecall with extreme care. +CallType constant CALLTYPE_DELEGATECALL = CallType.wrap(0xFF); + +uint256 constant MODULE_TYPE_VALIDATOR = 1; +uint256 constant MODULE_TYPE_EXECUTOR = 2; +uint256 constant MODULE_TYPE_FALLBACK = 3; +uint256 constant MODULE_TYPE_HOOK = 4; +uint256 constant MODULE_TYPE_POLICY = 5; +uint256 constant MODULE_TYPE_SIGNER = 6; + ValidationType constant VALIDATION_TYPE_ROOT = ValidationType.wrap(0x00); ValidationType constant VALIDATION_TYPE_VALIDATOR = ValidationType.wrap(0x01); ValidationType constant VALIDATION_TYPE_PERMISSION = ValidationType.wrap(0x02); + +// TODO: change this -- recalculate +bytes32 constant SELECTOR_MANAGER_STORAGE_SLOT = 0x7c341349a4360fdd5d5bc07e69f325dc6aaea3eb018b3e0ea7e53cc0bb0d6f3b; +// bytes32(uint256(keccak256('kernel.v3.executor')) - 1) +bytes32 constant EXECUTOR_MANAGER_STORAGE_SLOT = 0x1bbee3173dbdc223633258c9f337a0fff8115f206d302bea0ed3eac003b68b86; +// bytes32(uint256(keccak256('kernel.v3.hook')) - 1) +bytes32 constant HOOK_MANAGER_STORAGE_SLOT = 0x4605d5f70bb605094b2e761eccdc27bed9a362d8612792676bf3fb9b12832ffc; +// bytes32(uint256(keccak256('kernel.v3.validation')) - 1) +bytes32 constant VALIDATION_MANAGER_STORAGE_SLOT = 0x7bcaa2ced2a71450ed5a9a1b4848e8e5206dbc3f06011e595f7f55428cc6f84f; +bytes32 constant ERC1967_IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; + diff --git a/src/types/Error.sol b/src/types/Error.sol index f11c198f..5803cc87 100644 --- a/src/types/Error.sol +++ b/src/types/Error.sol @@ -7,4 +7,12 @@ error InvalidValidator(); error NotImplemented(); +error NotInstalled(); + error InstallSignatureVerificationFailed(); + +error InvalidRootValidation(); +error NotSupportedCallType(); +error NotSupportedExecType(); + +error InvalidSelector(); diff --git a/src/types/Structs.sol b/src/types/Structs.sol new file mode 100644 index 00000000..81b7706f --- /dev/null +++ b/src/types/Structs.sol @@ -0,0 +1,14 @@ + +struct Install { + uint256 moduleType; + address module; + bytes moduleData; + bytes internalData; +} + +struct Uninstall { + uint256 moduleType; + address module; + bytes data; +} + diff --git a/src/types/Types.sol b/src/types/Types.sol index f56afc80..1bd763d3 100644 --- a/src/types/Types.sol +++ b/src/types/Types.sol @@ -12,7 +12,38 @@ type ValidationId is bytes20; type ValidationType is bytes1; +// Custom type for improved developer experience +type ExecMode is bytes32; + +type CallType is bytes1; + +type ExecType is bytes1; + +type ExecModeSelector is bytes4; + +type ExecModePayload is bytes22; + using {vTypeEqual as ==} for ValidationType global; +using {eqCallType as ==} for CallType global; +using {notEqCallType as !=} for CallType global; +using {vIdentifierNotEqual as !=} for ValidationId global; +using {vIdentifierEqual as ==} for ValidationId global; + +function vIdentifierEqual(ValidationId a, ValidationId b) pure returns (bool) { + return ValidationId.unwrap(a) == ValidationId.unwrap(b); +} + +function vIdentifierNotEqual(ValidationId a, ValidationId b) pure returns (bool) { + return ValidationId.unwrap(a) != ValidationId.unwrap(b); +} + +function eqCallType(CallType a, CallType b) pure returns (bool) { + return CallType.unwrap(a) == CallType.unwrap(b); +} + +function notEqCallType(CallType a, CallType b) pure returns (bool) { + return CallType.unwrap(a) != CallType.unwrap(b); +} function vTypeEqual(ValidationType a, ValidationType b) pure returns (bool) { return ValidationType.unwrap(a) == ValidationType.unwrap(b); diff --git a/test/Kernel.t.sol b/test/Kernel.t.sol index 4dc9256b..8f778756 100644 --- a/test/Kernel.t.sol +++ b/test/Kernel.t.sol @@ -5,6 +5,7 @@ import {EntryPointLib} from "./utils/EntryPointLib.sol"; import {IEntryPoint} from "account-abstraction/interfaces/IEntryPoint.sol"; import {Kernel} from "src/Kernel.sol"; import {KernelFactory} from "src/KernelFactory.sol"; +import {LibERC7579} from "solady/accounts/LibERC7579.sol"; contract MockValidator { event MockInstall(bytes data); @@ -19,28 +20,189 @@ contract MockValidator { } } +contract MockCallee { + uint256 public bar; + string public data; + event Lorem(); + error Haha(); + function foo() external { + bar++; + emit Lorem(); + } + + function lorem() external { + data = "lorem ipsum"; + } + + function forceRevert() external { + revert Haha(); + } +} +struct Call { + address target; + uint256 value; + bytes data; +} contract KernelTest is Test { IEntryPoint ep; KernelFactory factory; MockValidator mockValidator; Kernel kernel; + MockCallee callee; + address executor; + + modifier unitTest { + vm.startPrank(address(ep)); + _; + vm.stopPrank(); + } + + modifier unitTestExecutor { + vm.startPrank(address(executor)); + _; + vm.stopPrank(); + } function setUp() external { ep = EntryPointLib.deploy(); factory = new KernelFactory(ep); mockValidator = new MockValidator(); + callee = new MockCallee(); + executor = makeAddr("Executor"); _initialize(); } function _initialize() internal { kernel = factory.deploy(abi.encode("Kernel Test")); + + vm.startPrank(address(ep)); + kernel.installModule(2, executor, abi.encode(hex"", "")); + vm.stopPrank(); } - function test_deploy() external { + function test_deploy() external unitTest { Kernel k = factory.deploy(hex""); } - function test_install_validator() external { + function test_install_validator() external unitTest { kernel.installModule(1, address(mockValidator), abi.encode(hex"deadbeef", "InternalData")); } + + function test_execute() external unitTest { + vm.expectEmit(address(callee)); + emit MockCallee.Lorem(); + kernel.execute(bytes32(0), abi.encodePacked(address(callee), uint256(0), abi.encodeWithSelector(MockCallee.foo.selector))); + assertEq(callee.bar(), 1); + } + + function test_execute_fail() external unitTest { + vm.expectRevert(MockCallee.Haha.selector); + kernel.execute(bytes32(0), abi.encodePacked(address(callee), uint256(0), abi.encodeWithSelector(MockCallee.forceRevert.selector))); + } + + function test_execute_fail_try() external unitTest { + kernel.execute(LibERC7579.encodeMode(bytes1(0x00), bytes1(0x01), bytes4(0), bytes22(0)), abi.encodePacked(address(callee), uint256(0), abi.encodeWithSelector(MockCallee.forceRevert.selector))); + } + + function test_execute_batch() external unitTest { + Call[] memory calls = new Call[](2); + calls[0] = Call({ + target : address(callee), + value : 0, + data : abi.encodeWithSelector(MockCallee.foo.selector) + }); + calls[1] = Call({ + target : address(callee), + value : 0, + data : abi.encodeWithSelector(MockCallee.lorem.selector) + }); + assertEq(callee.data(), ""); + vm.expectEmit(address(callee)); + emit MockCallee.Lorem(); + kernel.execute(LibERC7579.encodeMode(bytes1(0x01), bytes1(0x00), bytes4(0), bytes22(0)), abi.encode(calls)); + assertEq(callee.bar(), 1); + assertEq(callee.data(), "lorem ipsum"); + } + + function test_execute_batch_fail() external unitTest { + Call[] memory calls = new Call[](2); + calls[0] = Call({ + target : address(callee), + value : 0, + data : abi.encodeWithSelector(MockCallee.foo.selector) + }); + calls[1] = Call({ + target : address(callee), + value : 0, + data : abi.encodeWithSelector(MockCallee.forceRevert.selector) + }); + assertEq(callee.data(), ""); + vm.expectRevert(MockCallee.Haha.selector); + kernel.execute(LibERC7579.encodeMode(bytes1(0x01), bytes1(0x00), bytes4(0), bytes22(0)), abi.encode(calls)); + } + + function test_execute_batch_fail_try() external unitTest { + Call[] memory calls = new Call[](2); + calls[0] = Call({ + target : address(callee), + value : 0, + data : abi.encodeWithSelector(MockCallee.foo.selector) + }); + calls[1] = Call({ + target : address(callee), + value : 0, + data : abi.encodeWithSelector(MockCallee.forceRevert.selector) + }); + assertEq(callee.data(), ""); + kernel.execute(LibERC7579.encodeMode(bytes1(0x01), bytes1(0x01), bytes4(0), bytes22(0)), abi.encode(calls)); + assertEq(callee.bar(), 1); + } + + function test_execute_delegatecall() external unitTest { + vm.expectEmit(address(kernel)); + emit MockCallee.Lorem(); + kernel.execute(LibERC7579.encodeMode(bytes1(0xff), bytes1(0x00), bytes4(0), bytes22(0)), abi.encodePacked(address(callee), abi.encodeWithSelector(MockCallee.foo.selector))); + } + + function test_execute_delegatecall_fail() external unitTest { + vm.expectRevert(MockCallee.Haha.selector); + kernel.execute(LibERC7579.encodeMode(bytes1(0xff), bytes1(0x00), bytes4(0), bytes22(0)), abi.encodePacked(address(callee), abi.encodeWithSelector(MockCallee.forceRevert.selector))); + } + + function test_execute_delegatecall_fail_try() external unitTest { + kernel.execute(LibERC7579.encodeMode(bytes1(0xff), bytes1(0x01), bytes4(0), bytes22(0)), abi.encodePacked(address(callee), abi.encodeWithSelector(MockCallee.forceRevert.selector))); + } + + function test_execute_from_executor() external unitTestExecutor { + vm.expectEmit(address(callee)); + emit MockCallee.Lorem(); + kernel.executeFromExecutor(bytes32(0), abi.encodePacked(address(callee), uint256(0), abi.encodeWithSelector(MockCallee.foo.selector))); + assertEq(callee.bar(), 1); + } + + function test_execute_batch_from_executor() external unitTestExecutor { + Call[] memory calls = new Call[](2); + calls[0] = Call({ + target : address(callee), + value : 0, + data : abi.encodeWithSelector(MockCallee.foo.selector) + }); + calls[1] = Call({ + target : address(callee), + value : 0, + data : abi.encodeWithSelector(MockCallee.lorem.selector) + }); + assertEq(callee.data(), ""); + vm.expectEmit(address(callee)); + emit MockCallee.Lorem(); + kernel.executeFromExecutor(LibERC7579.encodeMode(bytes1(0x01), bytes1(0x00), bytes4(0), bytes22(0)), abi.encode(calls)); + assertEq(callee.bar(), 1); + assertEq(callee.data(), "lorem ipsum"); + } + + function test_execute_delegatecall_from_executor() external unitTestExecutor { + vm.expectEmit(address(kernel)); + emit MockCallee.Lorem(); + kernel.executeFromExecutor(LibERC7579.encodeMode(bytes1(0xff), bytes1(0x00), bytes4(0), bytes22(0)), abi.encodePacked(address(callee), abi.encodeWithSelector(MockCallee.foo.selector))); + } } From 784bf6233ac57531fa5d421192c30f0fb7b45490 Mon Sep 17 00:00:00 2001 From: leekt Date: Thu, 22 May 2025 05:45:04 +0900 Subject: [PATCH 007/121] removed coverage --- coverage/amber.png | Bin 141 -> 0 bytes coverage/cmd_line | 1 - coverage/emerald.png | Bin 141 -> 0 bytes coverage/gcov.css | 1101 ----------------- coverage/glass.png | Bin 167 -> 0 bytes coverage/index-sort-f.html | 141 --- coverage/index-sort-l.html | 141 --- coverage/index.html | 141 --- coverage/ruby.png | Bin 141 -> 0 bytes coverage/snow.png | Bin 141 -> 0 bytes coverage/src/Kernel.sol.func-c.html | 173 --- coverage/src/Kernel.sol.func.html | 173 --- coverage/src/Kernel.sol.gcov.html | 254 ---- coverage/src/KernelFactory.sol.func-c.html | 96 -- coverage/src/KernelFactory.sol.func.html | 96 -- coverage/src/KernelFactory.sol.gcov.html | 104 -- coverage/src/Lib4337.sol.func-c.html | 89 -- coverage/src/Lib4337.sol.func.html | 89 -- coverage/src/Lib4337.sol.gcov.html | 130 -- .../src/core/ExecutionManager.sol.func-c.html | 131 -- .../src/core/ExecutionManager.sol.func.html | 131 -- .../src/core/ExecutionManager.sol.gcov.html | 168 --- .../src/core/ExecutorManager.sol.func-c.html | 110 -- .../src/core/ExecutorManager.sol.func.html | 110 -- .../src/core/ExecutorManager.sol.gcov.html | 119 -- coverage/src/core/HookManager.sol.func-c.html | 103 -- coverage/src/core/HookManager.sol.func.html | 103 -- coverage/src/core/HookManager.sol.gcov.html | 113 -- .../src/core/ModuleManager.sol.func-c.html | 117 -- coverage/src/core/ModuleManager.sol.func.html | 117 -- coverage/src/core/ModuleManager.sol.gcov.html | 173 --- .../src/core/SelectorManager.sol.func-c.html | 103 -- .../src/core/SelectorManager.sol.func.html | 103 -- .../src/core/SelectorManager.sol.gcov.html | 127 -- .../core/ValidationManager.sol.func-c.html | 166 --- .../src/core/ValidationManager.sol.func.html | 166 --- .../src/core/ValidationManager.sol.gcov.html | 240 ---- coverage/src/core/index-sort-f.html | 165 --- coverage/src/core/index-sort-l.html | 165 --- coverage/src/core/index.html | 165 --- coverage/src/index-sort-f.html | 129 -- coverage/src/index-sort-l.html | 129 -- coverage/src/index.html | 129 -- coverage/test/Kernel.t.sol.func-c.html | 110 -- coverage/test/Kernel.t.sol.func.html | 110 -- coverage/test/Kernel.t.sol.gcov.html | 284 ----- coverage/test/index-sort-f.html | 105 -- coverage/test/index-sort-l.html | 105 -- coverage/test/index.html | 105 -- .../test/utils/EntryPointLib.sol.func-c.html | 82 -- .../test/utils/EntryPointLib.sol.func.html | 82 -- .../test/utils/EntryPointLib.sol.gcov.html | 92 -- coverage/test/utils/index-sort-f.html | 105 -- coverage/test/utils/index-sort-l.html | 105 -- coverage/test/utils/index.html | 105 -- coverage/updown.png | Bin 117 -> 0 bytes 56 files changed, 7401 deletions(-) delete mode 100644 coverage/amber.png delete mode 100644 coverage/cmd_line delete mode 100644 coverage/emerald.png delete mode 100644 coverage/gcov.css delete mode 100644 coverage/glass.png delete mode 100644 coverage/index-sort-f.html delete mode 100644 coverage/index-sort-l.html delete mode 100644 coverage/index.html delete mode 100644 coverage/ruby.png delete mode 100644 coverage/snow.png delete mode 100644 coverage/src/Kernel.sol.func-c.html delete mode 100644 coverage/src/Kernel.sol.func.html delete mode 100644 coverage/src/Kernel.sol.gcov.html delete mode 100644 coverage/src/KernelFactory.sol.func-c.html delete mode 100644 coverage/src/KernelFactory.sol.func.html delete mode 100644 coverage/src/KernelFactory.sol.gcov.html delete mode 100644 coverage/src/Lib4337.sol.func-c.html delete mode 100644 coverage/src/Lib4337.sol.func.html delete mode 100644 coverage/src/Lib4337.sol.gcov.html delete mode 100644 coverage/src/core/ExecutionManager.sol.func-c.html delete mode 100644 coverage/src/core/ExecutionManager.sol.func.html delete mode 100644 coverage/src/core/ExecutionManager.sol.gcov.html delete mode 100644 coverage/src/core/ExecutorManager.sol.func-c.html delete mode 100644 coverage/src/core/ExecutorManager.sol.func.html delete mode 100644 coverage/src/core/ExecutorManager.sol.gcov.html delete mode 100644 coverage/src/core/HookManager.sol.func-c.html delete mode 100644 coverage/src/core/HookManager.sol.func.html delete mode 100644 coverage/src/core/HookManager.sol.gcov.html delete mode 100644 coverage/src/core/ModuleManager.sol.func-c.html delete mode 100644 coverage/src/core/ModuleManager.sol.func.html delete mode 100644 coverage/src/core/ModuleManager.sol.gcov.html delete mode 100644 coverage/src/core/SelectorManager.sol.func-c.html delete mode 100644 coverage/src/core/SelectorManager.sol.func.html delete mode 100644 coverage/src/core/SelectorManager.sol.gcov.html delete mode 100644 coverage/src/core/ValidationManager.sol.func-c.html delete mode 100644 coverage/src/core/ValidationManager.sol.func.html delete mode 100644 coverage/src/core/ValidationManager.sol.gcov.html delete mode 100644 coverage/src/core/index-sort-f.html delete mode 100644 coverage/src/core/index-sort-l.html delete mode 100644 coverage/src/core/index.html delete mode 100644 coverage/src/index-sort-f.html delete mode 100644 coverage/src/index-sort-l.html delete mode 100644 coverage/src/index.html delete mode 100644 coverage/test/Kernel.t.sol.func-c.html delete mode 100644 coverage/test/Kernel.t.sol.func.html delete mode 100644 coverage/test/Kernel.t.sol.gcov.html delete mode 100644 coverage/test/index-sort-f.html delete mode 100644 coverage/test/index-sort-l.html delete mode 100644 coverage/test/index.html delete mode 100644 coverage/test/utils/EntryPointLib.sol.func-c.html delete mode 100644 coverage/test/utils/EntryPointLib.sol.func.html delete mode 100644 coverage/test/utils/EntryPointLib.sol.gcov.html delete mode 100644 coverage/test/utils/index-sort-f.html delete mode 100644 coverage/test/utils/index-sort-l.html delete mode 100644 coverage/test/utils/index.html delete mode 100644 coverage/updown.png diff --git a/coverage/amber.png b/coverage/amber.png deleted file mode 100644 index 2cab170d8359081983a4e343848dfe06bc490f12..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 141 zcmeAS@N?(olHy`uVBq!ia0vp^j3CU&3?x-=hn)ga>?NMQuI!iC1^G2tW}LqE04T&+ z;1OBOz`!j8!i<;h*8KqrvZOouIx;Y9?C1WI$O`1M1^9%x{(levWG?NMQuI!iC1^Jb!lvI6;R0X`wF(yt=9xVZRt1vCRixIA4P dLn>}1Cji+@42)0J?}79&c)I$ztaD0e0sy@GAL0N2 diff --git a/coverage/gcov.css b/coverage/gcov.css deleted file mode 100644 index 6c23ba93..00000000 --- a/coverage/gcov.css +++ /dev/null @@ -1,1101 +0,0 @@ -/* All views: initial background and text color */ -body -{ - color: #000000; - background-color: #ffffff; -} - -/* All views: standard link format*/ -a:link -{ - color: #284fa8; - text-decoration: underline; -} - -/* All views: standard link - visited format */ -a:visited -{ - color: #00cb40; - text-decoration: underline; -} - -/* All views: standard link - activated format */ -a:active -{ - color: #ff0040; - text-decoration: underline; -} - -/* All views: main title format */ -td.title -{ - text-align: center; - padding-bottom: 10px; - font-family: sans-serif; - font-size: 20pt; - font-style: italic; - font-weight: bold; -} -/* "Line coverage date bins" leader */ -td.subTableHeader -{ - text-align: center; - padding-bottom: 6px; - font-family: sans-serif; - font-weight: bold; - vertical-align: center; -} - -/* All views: header item format */ -td.headerItem -{ - text-align: right; - padding-right: 6px; - font-family: sans-serif; - font-weight: bold; - vertical-align: top; - white-space: nowrap; -} - -/* All views: header item value format */ -td.headerValue -{ - text-align: left; - color: #284fa8; - font-family: sans-serif; - font-weight: bold; - white-space: nowrap; -} - -/* All views: header item coverage table heading */ -td.headerCovTableHead -{ - text-align: center; - padding-right: 6px; - padding-left: 6px; - padding-bottom: 0px; - font-family: sans-serif; - white-space: nowrap; -} - -/* All views: header item coverage table entry */ -td.headerCovTableEntry -{ - text-align: right; - color: #284fa8; - font-family: sans-serif; - font-weight: bold; - white-space: nowrap; - padding-left: 12px; - padding-right: 4px; - background-color: #dae7fe; -} - -/* All views: header item coverage table entry for high coverage rate */ -td.headerCovTableEntryHi -{ - text-align: right; - color: #000000; - font-family: sans-serif; - font-weight: bold; - white-space: nowrap; - padding-left: 12px; - padding-right: 4px; - background-color: #a7fc9d; -} - -/* All views: header item coverage table entry for medium coverage rate */ -td.headerCovTableEntryMed -{ - text-align: right; - color: #000000; - font-family: sans-serif; - font-weight: bold; - white-space: nowrap; - padding-left: 12px; - padding-right: 4px; - background-color: #ffea20; -} - -/* All views: header item coverage table entry for ow coverage rate */ -td.headerCovTableEntryLo -{ - text-align: right; - color: #000000; - font-family: sans-serif; - font-weight: bold; - white-space: nowrap; - padding-left: 12px; - padding-right: 4px; - background-color: #ff0000; -} - -/* All views: header legend value for legend entry */ -td.headerValueLeg -{ - text-align: left; - color: #000000; - font-family: sans-serif; - font-size: 80%; - white-space: nowrap; - padding-top: 4px; -} - -/* All views: color of horizontal ruler */ -td.ruler -{ - background-color: #6688d4; -} - -/* All views: version string format */ -td.versionInfo -{ - text-align: center; - padding-top: 2px; - font-family: sans-serif; - font-style: italic; -} - -/* Directory view/File view (all)/Test case descriptions: - table headline format */ -td.tableHead -{ - text-align: center; - color: #ffffff; - background-color: #6688d4; - font-family: sans-serif; - font-size: 120%; - font-weight: bold; - white-space: nowrap; - padding-left: 4px; - padding-right: 4px; -} - -span.tableHeadSort -{ - padding-right: 4px; -} - -/* Directory view/File view (all): filename entry format */ -td.coverFile -{ - text-align: left; - padding-left: 10px; - padding-right: 20px; - color: #284fa8; - background-color: #dae7fe; - font-family: monospace; -} - -/* Directory view/File view (all): directory name entry format */ -td.coverDirectory -{ - text-align: left; - padding-left: 10px; - padding-right: 20px; - color: #284fa8; - background-color: #b8d0ff; - font-family: monospace; -} - -/* Directory view/File view (all): filename entry format */ -td.overallOwner -{ - text-align: center; - font-weight: bold; - font-family: sans-serif; - background-color: #dae7fe; - padding-right: 10px; - padding-left: 10px; -} - -/* Directory view/File view (all): filename entry format */ -td.ownerName -{ - text-align: right; - font-style: italic; - font-family: sans-serif; - background-color: #E5DBDB; - padding-right: 10px; - padding-left: 20px; -} - -/* Directory view/File view (all): bar-graph entry format*/ -td.coverBar -{ - padding-left: 10px; - padding-right: 10px; - background-color: #dae7fe; -} - -/* Directory view/File view (all): bar-graph entry format*/ -td.owner_coverBar -{ - padding-left: 10px; - padding-right: 10px; - background-color: #E5DBDB; -} - -/* Directory view/File view (all): bar-graph outline color */ -td.coverBarOutline -{ - background-color: #000000; -} - -/* Directory view/File view (all): percentage entry for files with - high coverage rate */ -td.coverPerHi -{ - text-align: right; - padding-left: 10px; - padding-right: 10px; - background-color: #a7fc9d; - font-weight: bold; - font-family: sans-serif; -} - -/* 'owner' entry: slightly lighter color than 'coverPerHi' */ -td.owner_coverPerHi -{ - text-align: right; - padding-left: 10px; - padding-right: 10px; - background-color: #82E0AA; - font-weight: bold; - font-family: sans-serif; -} - -/* Directory view/File view (all): line count entry */ -td.coverNumDflt -{ - text-align: right; - padding-left: 10px; - padding-right: 10px; - background-color: #dae7fe; - white-space: nowrap; - font-family: sans-serif; -} - -/* td background color and font for the 'owner' section of the table */ -td.ownerTla -{ - text-align: right; - padding-left: 10px; - padding-right: 10px; - background-color: #E5DBDB; - white-space: nowrap; - font-family: sans-serif; - font-style: italic; -} - -/* Directory view/File view (all): line count entry for files with - high coverage rate */ -td.coverNumHi -{ - text-align: right; - padding-left: 10px; - padding-right: 10px; - background-color: #a7fc9d; - white-space: nowrap; - font-family: sans-serif; -} - -td.owner_coverNumHi -{ - text-align: right; - padding-left: 10px; - padding-right: 10px; - background-color: #82E0AA; - white-space: nowrap; - font-family: sans-serif; -} - -/* Directory view/File view (all): percentage entry for files with - medium coverage rate */ -td.coverPerMed -{ - text-align: right; - padding-left: 10px; - padding-right: 10px; - background-color: #ffea20; - font-weight: bold; - font-family: sans-serif; -} - -td.owner_coverPerMed -{ - text-align: right; - padding-left: 10px; - padding-right: 10px; - background-color: #F9E79F; - font-weight: bold; - font-family: sans-serif; -} - -/* Directory view/File view (all): line count entry for files with - medium coverage rate */ -td.coverNumMed -{ - text-align: right; - padding-left: 10px; - padding-right: 10px; - background-color: #ffea20; - white-space: nowrap; - font-family: sans-serif; -} - -td.owner_coverNumMed -{ - text-align: right; - padding-left: 10px; - padding-right: 10px; - background-color: #F9E79F; - white-space: nowrap; - font-family: sans-serif; -} - -/* Directory view/File view (all): percentage entry for files with - low coverage rate */ -td.coverPerLo -{ - text-align: right; - padding-left: 10px; - padding-right: 10px; - background-color: #ff0000; - font-weight: bold; - font-family: sans-serif; -} - -td.owner_coverPerLo -{ - text-align: right; - padding-left: 10px; - padding-right: 10px; - background-color: #EC7063; - font-weight: bold; - font-family: sans-serif; -} - -/* Directory view/File view (all): line count entry for files with - low coverage rate */ -td.coverNumLo -{ - text-align: right; - padding-left: 10px; - padding-right: 10px; - background-color: #ff0000; - white-space: nowrap; - font-family: sans-serif; -} - -td.owner_coverNumLo -{ - text-align: right; - padding-left: 10px; - padding-right: 10px; - background-color: #EC7063; - white-space: nowrap; - font-family: sans-serif; -} - -/* File view (all): "show/hide details" link format */ -a.detail:link -{ - color: #b8d0ff; - font-size:80%; -} - -/* File view (all): "show/hide details" link - visited format */ -a.detail:visited -{ - color: #b8d0ff; - font-size:80%; -} - -/* File view (all): "show/hide details" link - activated format */ -a.detail:active -{ - color: #ffffff; - font-size:80%; -} - -/* File view (detail): test name entry */ -td.testName -{ - text-align: right; - padding-right: 10px; - background-color: #dae7fe; - font-family: sans-serif; -} - -/* File view (detail): test percentage entry */ -td.testPer -{ - text-align: right; - padding-left: 10px; - padding-right: 10px; - background-color: #dae7fe; - font-family: sans-serif; -} - -/* File view (detail): test lines count entry */ -td.testNum -{ - text-align: right; - padding-left: 10px; - padding-right: 10px; - background-color: #dae7fe; - font-family: sans-serif; -} - -/* Test case descriptions: test name format*/ -dt -{ - font-family: sans-serif; - font-weight: bold; -} - -/* Test case descriptions: description table body */ -td.testDescription -{ - padding-top: 10px; - padding-left: 30px; - padding-bottom: 10px; - padding-right: 30px; - background-color: #dae7fe; -} - -/* Source code view: function entry */ -td.coverFn -{ - text-align: left; - padding-left: 10px; - padding-right: 20px; - color: #284fa8; - background-color: #dae7fe; - font-family: monospace; -} - -/* Source code view: function entry zero count*/ -td.coverFnLo -{ - text-align: right; - padding-left: 10px; - padding-right: 10px; - background-color: #ff0000; - font-weight: bold; - font-family: sans-serif; -} - -/* Source code view: function entry nonzero count*/ -td.coverFnHi -{ - text-align: right; - padding-left: 10px; - padding-right: 10px; - background-color: #dae7fe; - font-weight: bold; - font-family: sans-serif; -} - -td.coverFnAlias -{ - text-align: right; - padding-left: 10px; - padding-right: 20px; - color: #284fa8; - /* make this a slightly different color than the leader - otherwise, - otherwise the alias is hard to distinguish in the table */ - background-color: #E5DBDB; /* very light pale grey/blue */ - font-family: monospace; -} - -/* Source code view: function entry zero count*/ -td.coverFnAliasLo -{ - text-align: right; - padding-left: 10px; - padding-right: 10px; - background-color: #EC7063; /* lighter red */ - font-family: sans-serif; -} - -/* Source code view: function entry nonzero count*/ -td.coverFnAliasHi -{ - text-align: right; - padding-left: 10px; - padding-right: 10px; - background-color: #dae7fe; - font-weight: bold; - font-family: sans-serif; -} - -/* Source code view: source code format */ -pre.source -{ - font-family: monospace; - white-space: pre; - margin-top: 2px; -} - -/* elided/removed code */ -span.elidedSource -{ - font-family: sans-serif; - /*font-size: 8pt; */ - font-style: italic; - background-color: lightgrey; -} - -/* Source code view: line number format */ -span.lineNum -{ - background-color: #efe383; -} - -/* Source code view: line number format when there are deleted - lines in the corresponding location */ -span.lineNumWithDelete -{ - foreground-color: #efe383; - background-color: lightgrey; -} - -/* Source code view: format for Cov legend */ -span.coverLegendCov -{ - padding-left: 10px; - padding-right: 10px; - padding-bottom: 2px; - background-color: #cad7fe; -} - -/* Source code view: format for NoCov legend */ -span.coverLegendNoCov -{ - padding-left: 10px; - padding-right: 10px; - padding-bottom: 2px; - background-color: #ff6230; -} - -/* Source code view: format for the source code heading line */ -pre.sourceHeading -{ - white-space: pre; - font-family: monospace; - font-weight: bold; - margin: 0px; -} - -/* All views: header legend value for low rate */ -td.headerValueLegL -{ - font-family: sans-serif; - text-align: center; - white-space: nowrap; - padding-left: 4px; - padding-right: 2px; - background-color: #ff0000; - font-size: 80%; -} - -/* All views: header legend value for med rate */ -td.headerValueLegM -{ - font-family: sans-serif; - text-align: center; - white-space: nowrap; - padding-left: 2px; - padding-right: 2px; - background-color: #ffea20; - font-size: 80%; -} - -/* All views: header legend value for hi rate */ -td.headerValueLegH -{ - font-family: sans-serif; - text-align: center; - white-space: nowrap; - padding-left: 2px; - padding-right: 4px; - background-color: #a7fc9d; - font-size: 80%; -} - -/* All views except source code view: legend format for low coverage */ -span.coverLegendCovLo -{ - padding-left: 10px; - padding-right: 10px; - padding-top: 2px; - background-color: #ff0000; -} - -/* All views except source code view: legend format for med coverage */ -span.coverLegendCovMed -{ - padding-left: 10px; - padding-right: 10px; - padding-top: 2px; - background-color: #ffea20; -} - -/* All views except source code view: legend format for hi coverage */ -span.coverLegendCovHi -{ - padding-left: 10px; - padding-right: 10px; - padding-top: 2px; - background-color: #a7fc9d; -} - -a.branchTla:link -{ - color: #000000; -} - -a.branchTla:visited -{ - color: #000000; -} - -/* Source code view/table entry background: format for lines classified as "Uncovered New Code (+ => 0): -Newly added code is not tested" */ -td.tlaUNC -{ - text-align: right; - background-color: #FF6230; -} -td.tlaBgUNC { - background-color: #FF6230; -} - -/* Source code view/table entry background: format for lines classified as "Uncovered New Code (+ => 0): -Newly added code is not tested" */ -span.tlaUNC -{ - text-align: left; - background-color: #FF6230; -} -span.tlaBgUNC { - background-color: #FF6230; -} -a.tlaBgUNC { - background-color: #FF6230; - color: #000000; -} - -td.headerCovTableHeadUNC { - text-align: center; - padding-right: 6px; - padding-left: 6px; - padding-bottom: 0px; - font-family: sans-serif; - white-space: nowrap; - background-color: #FF6230; -} - -/* Source code view/table entry background: format for lines classified as "Lost Baseline Coverage (1 => 0): -Unchanged code is no longer tested" */ -td.tlaLBC -{ - text-align: right; - background-color: #FF6230; -} -td.tlaBgLBC { - background-color: #FF6230; -} - -/* Source code view/table entry background: format for lines classified as "Lost Baseline Coverage (1 => 0): -Unchanged code is no longer tested" */ -span.tlaLBC -{ - text-align: left; - background-color: #FF6230; -} -span.tlaBgLBC { - background-color: #FF6230; -} -a.tlaBgLBC { - background-color: #FF6230; - color: #000000; -} - -td.headerCovTableHeadLBC { - text-align: center; - padding-right: 6px; - padding-left: 6px; - padding-bottom: 0px; - font-family: sans-serif; - white-space: nowrap; - background-color: #FF6230; -} - -/* Source code view/table entry background: format for lines classified as "Uncovered Included Code (# => 0): -Previously unused code is untested" */ -td.tlaUIC -{ - text-align: right; - background-color: #FF6230; -} -td.tlaBgUIC { - background-color: #FF6230; -} - -/* Source code view/table entry background: format for lines classified as "Uncovered Included Code (# => 0): -Previously unused code is untested" */ -span.tlaUIC -{ - text-align: left; - background-color: #FF6230; -} -span.tlaBgUIC { - background-color: #FF6230; -} -a.tlaBgUIC { - background-color: #FF6230; - color: #000000; -} - -td.headerCovTableHeadUIC { - text-align: center; - padding-right: 6px; - padding-left: 6px; - padding-bottom: 0px; - font-family: sans-serif; - white-space: nowrap; - background-color: #FF6230; -} - -/* Source code view/table entry background: format for lines classified as "Uncovered Baseline Code (0 => 0): -Unchanged code was untested before, is untested now" */ -td.tlaUBC -{ - text-align: right; - background-color: #FF6230; -} -td.tlaBgUBC { - background-color: #FF6230; -} - -/* Source code view/table entry background: format for lines classified as "Uncovered Baseline Code (0 => 0): -Unchanged code was untested before, is untested now" */ -span.tlaUBC -{ - text-align: left; - background-color: #FF6230; -} -span.tlaBgUBC { - background-color: #FF6230; -} -a.tlaBgUBC { - background-color: #FF6230; - color: #000000; -} - -td.headerCovTableHeadUBC { - text-align: center; - padding-right: 6px; - padding-left: 6px; - padding-bottom: 0px; - font-family: sans-serif; - white-space: nowrap; - background-color: #FF6230; -} - -/* Source code view/table entry background: format for lines classified as "Gained Baseline Coverage (0 => 1): -Unchanged code is tested now" */ -td.tlaGBC -{ - text-align: right; - background-color: #CAD7FE; -} -td.tlaBgGBC { - background-color: #CAD7FE; -} - -/* Source code view/table entry background: format for lines classified as "Gained Baseline Coverage (0 => 1): -Unchanged code is tested now" */ -span.tlaGBC -{ - text-align: left; - background-color: #CAD7FE; -} -span.tlaBgGBC { - background-color: #CAD7FE; -} -a.tlaBgGBC { - background-color: #CAD7FE; - color: #000000; -} - -td.headerCovTableHeadGBC { - text-align: center; - padding-right: 6px; - padding-left: 6px; - padding-bottom: 0px; - font-family: sans-serif; - white-space: nowrap; - background-color: #CAD7FE; -} - -/* Source code view/table entry background: format for lines classified as "Gained Included Coverage (# => 1): -Previously unused code is tested now" */ -td.tlaGIC -{ - text-align: right; - background-color: #CAD7FE; -} -td.tlaBgGIC { - background-color: #CAD7FE; -} - -/* Source code view/table entry background: format for lines classified as "Gained Included Coverage (# => 1): -Previously unused code is tested now" */ -span.tlaGIC -{ - text-align: left; - background-color: #CAD7FE; -} -span.tlaBgGIC { - background-color: #CAD7FE; -} -a.tlaBgGIC { - background-color: #CAD7FE; - color: #000000; -} - -td.headerCovTableHeadGIC { - text-align: center; - padding-right: 6px; - padding-left: 6px; - padding-bottom: 0px; - font-family: sans-serif; - white-space: nowrap; - background-color: #CAD7FE; -} - -/* Source code view/table entry background: format for lines classified as "Gained New Coverage (+ => 1): -Newly added code is tested" */ -td.tlaGNC -{ - text-align: right; - background-color: #CAD7FE; -} -td.tlaBgGNC { - background-color: #CAD7FE; -} - -/* Source code view/table entry background: format for lines classified as "Gained New Coverage (+ => 1): -Newly added code is tested" */ -span.tlaGNC -{ - text-align: left; - background-color: #CAD7FE; -} -span.tlaBgGNC { - background-color: #CAD7FE; -} -a.tlaBgGNC { - background-color: #CAD7FE; - color: #000000; -} - -td.headerCovTableHeadGNC { - text-align: center; - padding-right: 6px; - padding-left: 6px; - padding-bottom: 0px; - font-family: sans-serif; - white-space: nowrap; - background-color: #CAD7FE; -} - -/* Source code view/table entry background: format for lines classified as "Covered Baseline Code (1 => 1): -Unchanged code was tested before and is still tested" */ -td.tlaCBC -{ - text-align: right; - background-color: #CAD7FE; -} -td.tlaBgCBC { - background-color: #CAD7FE; -} - -/* Source code view/table entry background: format for lines classified as "Covered Baseline Code (1 => 1): -Unchanged code was tested before and is still tested" */ -span.tlaCBC -{ - text-align: left; - background-color: #CAD7FE; -} -span.tlaBgCBC { - background-color: #CAD7FE; -} -a.tlaBgCBC { - background-color: #CAD7FE; - color: #000000; -} - -td.headerCovTableHeadCBC { - text-align: center; - padding-right: 6px; - padding-left: 6px; - padding-bottom: 0px; - font-family: sans-serif; - white-space: nowrap; - background-color: #CAD7FE; -} - -/* Source code view/table entry background: format for lines classified as "Excluded Uncovered Baseline (0 => #): -Previously untested code is unused now" */ -td.tlaEUB -{ - text-align: right; - background-color: #FFFFFF; -} -td.tlaBgEUB { - background-color: #FFFFFF; -} - -/* Source code view/table entry background: format for lines classified as "Excluded Uncovered Baseline (0 => #): -Previously untested code is unused now" */ -span.tlaEUB -{ - text-align: left; - background-color: #FFFFFF; -} -span.tlaBgEUB { - background-color: #FFFFFF; -} -a.tlaBgEUB { - background-color: #FFFFFF; - color: #000000; -} - -td.headerCovTableHeadEUB { - text-align: center; - padding-right: 6px; - padding-left: 6px; - padding-bottom: 0px; - font-family: sans-serif; - white-space: nowrap; - background-color: #FFFFFF; -} - -/* Source code view/table entry background: format for lines classified as "Excluded Covered Baseline (1 => #): -Previously tested code is unused now" */ -td.tlaECB -{ - text-align: right; - background-color: #FFFFFF; -} -td.tlaBgECB { - background-color: #FFFFFF; -} - -/* Source code view/table entry background: format for lines classified as "Excluded Covered Baseline (1 => #): -Previously tested code is unused now" */ -span.tlaECB -{ - text-align: left; - background-color: #FFFFFF; -} -span.tlaBgECB { - background-color: #FFFFFF; -} -a.tlaBgECB { - background-color: #FFFFFF; - color: #000000; -} - -td.headerCovTableHeadECB { - text-align: center; - padding-right: 6px; - padding-left: 6px; - padding-bottom: 0px; - font-family: sans-serif; - white-space: nowrap; - background-color: #FFFFFF; -} - -/* Source code view/table entry background: format for lines classified as "Deleted Uncovered Baseline (0 => -): -Previously untested code has been deleted" */ -td.tlaDUB -{ - text-align: right; - background-color: #FFFFFF; -} -td.tlaBgDUB { - background-color: #FFFFFF; -} - -/* Source code view/table entry background: format for lines classified as "Deleted Uncovered Baseline (0 => -): -Previously untested code has been deleted" */ -span.tlaDUB -{ - text-align: left; - background-color: #FFFFFF; -} -span.tlaBgDUB { - background-color: #FFFFFF; -} -a.tlaBgDUB { - background-color: #FFFFFF; - color: #000000; -} - -td.headerCovTableHeadDUB { - text-align: center; - padding-right: 6px; - padding-left: 6px; - padding-bottom: 0px; - font-family: sans-serif; - white-space: nowrap; - background-color: #FFFFFF; -} - -/* Source code view/table entry background: format for lines classified as "Deleted Covered Baseline (1 => -): -Previously tested code has been deleted" */ -td.tlaDCB -{ - text-align: right; - background-color: #FFFFFF; -} -td.tlaBgDCB { - background-color: #FFFFFF; -} - -/* Source code view/table entry background: format for lines classified as "Deleted Covered Baseline (1 => -): -Previously tested code has been deleted" */ -span.tlaDCB -{ - text-align: left; - background-color: #FFFFFF; -} -span.tlaBgDCB { - background-color: #FFFFFF; -} -a.tlaBgDCB { - background-color: #FFFFFF; - color: #000000; -} - -td.headerCovTableHeadDCB { - text-align: center; - padding-right: 6px; - padding-left: 6px; - padding-bottom: 0px; - font-family: sans-serif; - white-space: nowrap; - background-color: #FFFFFF; -} - -/* Source code view: format for date/owner bin that is not hit */ -span.missBins -{ - background-color: #ff0000 /* red */ -} diff --git a/coverage/glass.png b/coverage/glass.png deleted file mode 100644 index e1abc00680a3093c49fdb775ae6bdb6764c95af2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 167 zcmeAS@N?(olHy`uVBq!ia0vp^j3CU&3?x-=hn)gaEa{HEjtmSN`?>!lvI6;R0X`wF z|Ns97GD8ntt^-nxB|(0{3=Yq3q=7g|-tI089jvk*Kn`btM`SSr1Gf+eGhVt|_XjA* zUgGKN%6^Gmn4d%Ph(nkFP>9RZ#WAE}PI3Z}&BVayv3^M*kj3EX>gTe~DWM4f=_Dpv diff --git a/coverage/index-sort-f.html b/coverage/index-sort-f.html deleted file mode 100644 index 1688fa01..00000000 --- a/coverage/index-sort-f.html +++ /dev/null @@ -1,141 +0,0 @@ - - - - - - - LCOV - lcov.info - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top levelCoverageTotalHit
Test:lcov.infoLines:37.1 %307114
Test Date:2025-05-22 05:44:20Functions:46.2 %6530
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Directory Sort by file nameLine Coverage Sort by line coverageFunction Coverage Sort by function coverage
Rate Total Hit Rate Total Hit
src/ -
19.2%19.2%
-
19.2 %991936.8 %197
src/core/ -
42.5%42.5%
-
42.5 %1938245.0 %4018
test/ -
81.8%81.8%
-
81.8 %11980.0 %54
test/utils/ -
100.0%
-
100.0 %44100.0 %11
-
-
- - - - -
Generated by: LCOV version 2.1-1
-
- - - diff --git a/coverage/index-sort-l.html b/coverage/index-sort-l.html deleted file mode 100644 index 4c40c775..00000000 --- a/coverage/index-sort-l.html +++ /dev/null @@ -1,141 +0,0 @@ - - - - - - - LCOV - lcov.info - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top levelCoverageTotalHit
Test:lcov.infoLines:37.1 %307114
Test Date:2025-05-22 05:44:20Functions:46.2 %6530
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Directory Sort by file nameLine Coverage Sort by line coverageFunction Coverage Sort by function coverage
Rate Total Hit Rate Total Hit
src/ -
19.2%19.2%
-
19.2 %991936.8 %197
src/core/ -
42.5%42.5%
-
42.5 %1938245.0 %4018
test/ -
81.8%81.8%
-
81.8 %11980.0 %54
test/utils/ -
100.0%
-
100.0 %44100.0 %11
-
-
- - - - -
Generated by: LCOV version 2.1-1
-
- - - diff --git a/coverage/index.html b/coverage/index.html deleted file mode 100644 index 7207c67c..00000000 --- a/coverage/index.html +++ /dev/null @@ -1,141 +0,0 @@ - - - - - - - LCOV - lcov.info - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top levelCoverageTotalHit
Test:lcov.infoLines:37.1 %307114
Test Date:2025-05-22 05:44:20Functions:46.2 %6530
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Directory Sort by file nameLine Coverage Sort by line coverageFunction Coverage Sort by function coverage
Rate Total Hit Rate Total Hit
src/ -
19.2%19.2%
-
19.2 %991936.8 %197
src/core/ -
42.5%42.5%
-
42.5 %1938245.0 %4018
test/ -
81.8%81.8%
-
81.8 %11980.0 %54
test/utils/ -
100.0%
-
100.0 %44100.0 %11
-
-
- - - - -
Generated by: LCOV version 2.1-1
-
- - - diff --git a/coverage/ruby.png b/coverage/ruby.png deleted file mode 100644 index 991b6d4ec9e78be165e3ef757eed1aada287364d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 141 zcmeAS@N?(olHy`uVBq!ia0vp^j3CU&3?x-=hn)ga>?NMQuI!iC1^FceV#7`HfI^%F z9+AZi4BSE>%y{W;-5;PJOS+@4BLl<6e(pbstUx|nfKQ0)e^Y%R^MdiLxj>4`)5S5Q b;#P73kj=!v_*DHKNFRfztDnm{r-UW|iOwIS diff --git a/coverage/snow.png b/coverage/snow.png deleted file mode 100644 index 2cdae107fceec6e7f02ac7acb4a34a82a540caa5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 141 zcmeAS@N?(olHy`uVBq!ia0vp^j3CU&3?x-=hn)ga>?NMQuI!iC1^MM!lvI6;R0X`wF|Ns97GD8ntt^-nBo-U3d c6}OTTfNUlP#;5A{K>8RwUHx3vIVCg!071?oo&W#< diff --git a/coverage/src/Kernel.sol.func-c.html b/coverage/src/Kernel.sol.func-c.html deleted file mode 100644 index ec9b1bc4..00000000 --- a/coverage/src/Kernel.sol.func-c.html +++ /dev/null @@ -1,173 +0,0 @@ - - - - - - - LCOV - lcov.info - src/Kernel.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src - Kernel.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:18.6 %7013
Test Date:2025-05-22 05:44:20Functions:35.7 %145
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by function hit count
Kernel._fallback0
Kernel._processUserOp0
Kernel._verifyInstallSignature0
Kernel.executeUserOp0
Kernel.fallback0
Kernel.isValidSignature0
Kernel.onlyEntryPointOrSelf0
Kernel.setRoot0
Kernel.validateUserOp0
Kernel.executeFromExecutor3
Kernel.execute9
Kernel._domainNameAndVersion14
Kernel.constructor14
Kernel.installModule15
-
-
- - - -
Generated by: LCOV version 2.1-1
-
- - - diff --git a/coverage/src/Kernel.sol.func.html b/coverage/src/Kernel.sol.func.html deleted file mode 100644 index 73aa92e9..00000000 --- a/coverage/src/Kernel.sol.func.html +++ /dev/null @@ -1,173 +0,0 @@ - - - - - - - LCOV - lcov.info - src/Kernel.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src - Kernel.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:18.6 %7013
Test Date:2025-05-22 05:44:20Functions:35.7 %145
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by function hit count
Kernel._domainNameAndVersion14
Kernel._fallback0
Kernel._processUserOp0
Kernel._verifyInstallSignature0
Kernel.constructor14
Kernel.execute9
Kernel.executeFromExecutor3
Kernel.executeUserOp0
Kernel.fallback0
Kernel.installModule15
Kernel.isValidSignature0
Kernel.onlyEntryPointOrSelf0
Kernel.setRoot0
Kernel.validateUserOp0
-
-
- - - -
Generated by: LCOV version 2.1-1
-
- - - diff --git a/coverage/src/Kernel.sol.gcov.html b/coverage/src/Kernel.sol.gcov.html deleted file mode 100644 index 1f0e6756..00000000 --- a/coverage/src/Kernel.sol.gcov.html +++ /dev/null @@ -1,254 +0,0 @@ - - - - - - - LCOV - lcov.info - src/Kernel.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src - Kernel.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:18.6 %7013
Test Date:2025-05-22 05:44:20Functions:35.7 %145
-
- - - - - - - - -

-
            Line data    Source code
-
-       1              : pragma solidity ^0.8.0;
-       2              : 
-       3              : import {IEntryPoint} from "account-abstraction/interfaces/IEntryPoint.sol";
-       4              : import {IAccount} from "account-abstraction/interfaces/IAccount.sol";
-       5              : import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol";
-       6              : import {IValidator} from "./interfaces/IERC7579Modules.sol";
-       7              : import "./types/Types.sol";
-       8              : import {ModuleManager, Install} from "./core/ModuleManager.sol";
-       9              : import {ExecutionManager} from "./core/ExecutionManager.sol";
-      10              : import {EIP712} from "solady/utils/EIP712.sol";
-      11              : import {Lib4337} from "./Lib4337.sol";
-      12              : import "./types/Error.sol";
-      13              : import "./types/Events.sol";
-      14              : 
-      15              : contract Kernel is ModuleManager, ExecutionManager, EIP712 {
-      16              :     IEntryPoint immutable entryPoint;
-      17              : 
-      18              :     error Unauthorized();
-      19              : 
-      20            0 :     modifier onlyEntryPointOrSelf() {
-      21            0 :         require(msg.sender == address(entryPoint) || msg.sender == address(this), Unauthorized());
-      22              :         _;
-      23              :     }
-      24              : 
-      25           14 :     constructor(IEntryPoint _entryPoint) {
-      26           14 :         entryPoint = _entryPoint;
-      27              :     }
-      28              : 
-      29           14 :     function _domainNameAndVersion() internal pure override returns (string memory name, string memory version) {
-      30           14 :         name = "Kernel";
-      31           14 :         version = "0.4.0";
-      32              :     }
-      33              : 
-      34              :     /// authentication
-      35              :     struct EnableModeSignature {
-      36              :         Install[] packages;
-      37              :         bytes enableSignature;
-      38              :         bytes userOpSignature;
-      39              :     }
-      40              : 
-      41            0 :     function validateUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash, uint256 missingAccountFunds)
-      42              :         external
-      43              :         payable
-      44              :         onlyEntryPointOrSelf
-      45              :         returns (uint256 validationData)
-      46              :     {
-      47            0 :         (ValidationId verifier, bytes32 opHash, bytes calldata userOpSignature) = _processUserOp(userOp, userOpHash);
-      48            0 :         validationData = _validateUserOp(verifier, opHash, userOp, userOpSignature);
-      49              :         assembly {
-      50            0 :             if missingAccountFunds {
-      51            0 :                 pop(call(gas(), caller(), missingAccountFunds, callvalue(), callvalue(), callvalue(), callvalue()))
-      52              :                 //ignore failure (its EntryPoint's job to verify, not account.)
-      53              :             }
-      54              :         }
-      55              :     }
-      56              : 
-      57            0 :     function _processUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash)
-      58              :         internal
-      59              :         returns (ValidationId verifier, bytes32 opHash, bytes calldata signature)
-      60              :     {
-      61              :         /*
-      62              :          userOp.nonce = vMode | vType | vId
-      63              :         */
-      64            0 :         (ValidationMode vMode, ValidationType vType, ValidationId vId) = _parseNonce(userOp.nonce);
-      65            0 :         signature = userOp.signature;
-      66            0 :         if (isEnable(vMode)) {
-      67            0 :             bool enableReplayable = isEnableReplayable(vMode);
-      68            0 :             EnableModeSignature calldata sig;
-      69              :             assembly {
-      70            0 :                 sig := signature.offset
-      71              :             }
-      72            0 :             _verifyInstallSignature(enableReplayable, sig.packages, sig.enableSignature);
-      73            0 :             _install(sig.packages);
-      74            0 :             signature = sig.userOpSignature;
-      75              :         }
-      76            0 :         _checkValidation(vMode, vType, vId);
-      77            0 :         opHash = isReplayable(vMode) ? Lib4337.chainAgnosticUserOpHash(msg.sender, userOp) : userOpHash;
-      78              :     }
-      79              : 
-      80            0 :     function isValidSignature(bytes32 hash, bytes calldata signature) external view returns (bytes4) {}
-      81              : 
-      82              :     /// execution
-      83            0 :     function executeUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash) external payable onlyEntryPointOrSelf {
-      84            0 :         (bool success, bytes memory ret) = address(this).delegatecall(userOp.callData[4:]);
-      85              :     }
-      86              : 
-      87            9 :     function execute(bytes32 mode, bytes calldata executionData) external payable onlyEntryPointOrSelf {
-      88            9 :         _execute(mode, executionData);
-      89              :     }
-      90              : 
-      91            3 :     function executeFromExecutor(bytes32 mode, bytes calldata executionData) external payable onlyExecutor {
-      92            3 :         _execute(mode, executionData);
-      93              :     }
-      94              :     
-      95            0 :     function _fallback() internal {
-      96            0 :         bytes4 selector = bytes4(msg.data);
-      97            0 :         SelectorConfig storage $ = _selectorConfig(selector);
-      98            0 :         if($.target == address(0)) {
-      99            0 :             revert InvalidSelector();
-     100              :         }
-     101            0 :         bytes memory hookData;
-     102            0 :         if(address($.hook) != address(0)) {
-     103            0 :             hookData = _preHook($.hook);
-     104              :         }
-     105              : 
-     106            0 :         bool success;
-     107            0 :         if($.callType == CallType.wrap(bytes1(0x00))) {
-     108            0 :             success = _call($.target, 0, msg.data);
-     109            0 :         } else if($.callType == CallType.wrap(bytes1(0xff))) {
-     110            0 :             success = _delegateCall($.target, msg.data);
-     111              :         }
-     112            0 :         if(!success) {
-     113            0 :             _onRevertThrow();
-     114              :         }
-     115            0 :         if(address($.hook) != address(0)) {
-     116            0 :             _postHook($.hook, hookData);
-     117              :         }
-     118              :     }
-     119              : 
-     120              :     /// management
-     121              :     struct InstallModuleDataFormat {
-     122              :         bytes installData;
-     123              :         bytes internalData;
-     124              :     }
-     125              : 
-     126           15 :     function installModule(uint256 moduleType, address module, bytes calldata initData) external payable onlyEntryPointOrSelf {
-     127           15 :         InstallModuleDataFormat calldata imdf;
-     128              :         assembly {
-     129           15 :             imdf := initData.offset
-     130              :         }
-     131           15 :         _installModule(moduleType, module, imdf.installData, imdf.internalData);
-     132              :     }
-     133              : 
-     134            0 :     function setRoot(ValidationId vId) external payable onlyEntryPointOrSelf {
-     135            0 :         _setRoot(vId);
-     136              :     }
-     137              : 
-     138              :     // NOTE : this ONLY allows root signature, for now
-     139            0 :     function installModule(bool replayable, Install[] calldata packages, bytes calldata signature) external {
-     140            0 :         if(_initialized()) {
-     141              :             // if 7702 or already initialized, use root signature to install module
-     142            0 :             require(_verifyInstallSignature(replayable, packages, signature), InstallSignatureVerificationFailed());
-     143            0 :             _install(packages);
-     144              :         } else {
-     145              :             // this is initialize
-     146              :             // require first package to be the root validator
-     147            0 :             require(packages.length > 0);
-     148            0 :             Install calldata root = packages[0];
-     149            0 :             _install(packages);
-     150            0 :             _setRoot(root);
-     151              :         }
-     152              :     }
-     153              : 
-     154            0 :     function _verifyInstallSignature(bool replayable, Install[] calldata packages, bytes calldata signature)
-     155              :         internal
-     156              :         view
-     157              :         returns (bool success)
-     158              :     {
-     159            0 :         ValidationId vId = _validationStorage().root;
-     160            0 :         function(bytes32) internal view returns(bytes32) hashTypedData =
-     161            0 :             replayable ? _hashTypedDataSansChainId : _hashTypedData;
-     162            0 :         bytes32 digest = hashTypedData(
-     163              :             keccak256(
-     164              :                 abi.encode(
-     165              :                     keccak256(
-     166              :                         "InstallPackages(Install[] packages)Install(uint256 moduleType,address module,bytes moduleData,bytes internalData)"
-     167              :                     ),
-     168              :                     _installHash(packages)
-     169              :                 )
-     170              :             )
-     171              :         );
-     172            0 :         _verifySignature(vId, address(this), digest, signature);
-     173              :     }
-     174              : 
-     175            0 :     fallback() external payable {
-     176            0 :         _fallback();
-     177              :     }
-     178              : }
-        
-
-
- - - - -
Generated by: LCOV version 2.1-1
-
- - - diff --git a/coverage/src/KernelFactory.sol.func-c.html b/coverage/src/KernelFactory.sol.func-c.html deleted file mode 100644 index 7faeb791..00000000 --- a/coverage/src/KernelFactory.sol.func-c.html +++ /dev/null @@ -1,96 +0,0 @@ - - - - - - - LCOV - lcov.info - src/KernelFactory.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src - KernelFactory.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:50.0 %126
Test Date:2025-05-22 05:44:20Functions:66.7 %32
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by function hit count
KernelFactory.deployWithAdditionalPackage0
KernelFactory.constructor14
KernelFactory.deploy15
-
-
- - - -
Generated by: LCOV version 2.1-1
-
- - - diff --git a/coverage/src/KernelFactory.sol.func.html b/coverage/src/KernelFactory.sol.func.html deleted file mode 100644 index 1ea9a2cb..00000000 --- a/coverage/src/KernelFactory.sol.func.html +++ /dev/null @@ -1,96 +0,0 @@ - - - - - - - LCOV - lcov.info - src/KernelFactory.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src - KernelFactory.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:50.0 %126
Test Date:2025-05-22 05:44:20Functions:66.7 %32
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by function hit count
KernelFactory.constructor14
KernelFactory.deploy15
KernelFactory.deployWithAdditionalPackage0
-
-
- - - -
Generated by: LCOV version 2.1-1
-
- - - diff --git a/coverage/src/KernelFactory.sol.gcov.html b/coverage/src/KernelFactory.sol.gcov.html deleted file mode 100644 index b7f3261b..00000000 --- a/coverage/src/KernelFactory.sol.gcov.html +++ /dev/null @@ -1,104 +0,0 @@ - - - - - - - LCOV - lcov.info - src/KernelFactory.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src - KernelFactory.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:50.0 %126
Test Date:2025-05-22 05:44:20Functions:66.7 %32
-
- - - - - - - - -

-
            Line data    Source code
-
-       1              : pragma solidity ^0.8.0;
-       2              : 
-       3              : import {Kernel, Install} from "./Kernel.sol";
-       4              : import {LibClone} from "solady/utils/LibClone.sol";
-       5              : import {IEntryPoint} from "account-abstraction/interfaces/IEntryPoint.sol";
-       6              : 
-       7              : contract KernelFactory {
-       8              :     Kernel public immutable template;
-       9              : 
-      10           14 :     constructor(IEntryPoint _entryPoint) {
-      11           14 :         template = new Kernel(_entryPoint);
-      12              :     }
-      13              : 
-      14           15 :     function deploy(bytes calldata initData) external payable returns (Kernel) {
-      15           15 :         bytes32 salt = keccak256(initData);
-      16           15 :         (bool deployed, address account) = LibClone.createDeterministicERC1967(msg.value, address(template), salt);
-      17           15 :         return Kernel(payable(account));
-      18              :     }
-      19              : 
-      20            0 :     function deployWithAdditionalPackage(bytes calldata initData, bool replayable, Install[] calldata packages, bytes calldata signature) external payable returns (Kernel) {
-      21            0 :         bytes32 salt = keccak256(initData);
-      22            0 :         (bool deployed, address account) = LibClone.createDeterministicERC1967(msg.value, address(template), salt);
-      23              : 
-      24            0 :         Kernel k = Kernel(payable(account));
-      25            0 :         k.installModule(replayable, packages, signature);
-      26            0 :         return k;
-      27              :     }
-      28              : }
-        
-
-
- - - - -
Generated by: LCOV version 2.1-1
-
- - - diff --git a/coverage/src/Lib4337.sol.func-c.html b/coverage/src/Lib4337.sol.func-c.html deleted file mode 100644 index add91332..00000000 --- a/coverage/src/Lib4337.sol.func-c.html +++ /dev/null @@ -1,89 +0,0 @@ - - - - - - - LCOV - lcov.info - src/Lib4337.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src - Lib4337.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:0.0 %170
Test Date:2025-05-22 05:44:20Functions:0.0 %20
-
- -
- - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by function hit count
Lib4337._hashTypedDataSansChainId0
Lib4337.chainAgnosticUserOpHash0
-
-
- - - -
Generated by: LCOV version 2.1-1
-
- - - diff --git a/coverage/src/Lib4337.sol.func.html b/coverage/src/Lib4337.sol.func.html deleted file mode 100644 index 2152f584..00000000 --- a/coverage/src/Lib4337.sol.func.html +++ /dev/null @@ -1,89 +0,0 @@ - - - - - - - LCOV - lcov.info - src/Lib4337.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src - Lib4337.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:0.0 %170
Test Date:2025-05-22 05:44:20Functions:0.0 %20
-
- -
- - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by function hit count
Lib4337._hashTypedDataSansChainId0
Lib4337.chainAgnosticUserOpHash0
-
-
- - - -
Generated by: LCOV version 2.1-1
-
- - - diff --git a/coverage/src/Lib4337.sol.gcov.html b/coverage/src/Lib4337.sol.gcov.html deleted file mode 100644 index cde3e4fb..00000000 --- a/coverage/src/Lib4337.sol.gcov.html +++ /dev/null @@ -1,130 +0,0 @@ - - - - - - - LCOV - lcov.info - src/Lib4337.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src - Lib4337.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:0.0 %170
Test Date:2025-05-22 05:44:20Functions:0.0 %20
-
- - - - - - - - -

-
            Line data    Source code
-
-       1              : pragma solidity ^0.8.0;
-       2              : 
-       3              : import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol";
-       4              : import {UserOperationLib} from "account-abstraction/core/UserOperationLib.sol";
-       5              : import {Eip7702Support} from "account-abstraction/core/Eip7702Support.sol";
-       6              : interface IERC5267 {
-       7              :     function eip712Domain()
-       8              :         external
-       9              :         view
-      10              :         returns (
-      11              :             bytes1 fields,
-      12              :             string memory name,
-      13              :             string memory version,
-      14              :             uint256 chainId,
-      15              :             address verifyingContract,
-      16              :             bytes32 salt,
-      17              :             uint256[] memory extensions
-      18              :         );
-      19              : }
-      20              : 
-      21              : library Lib4337 {
-      22              :     bytes32 internal constant _DOMAIN_TYPEHASH_SANS_CHAIN_ID =
-      23              :         0x91ab3d17e3a50a9d89e63fd30b92be7f5336b03b287bb946787a83a9d62a2766;
-      24            0 :     function chainAgnosticUserOpHash(address ep, PackedUserOperation calldata userOp) public view returns(bytes32) {
-      25            0 :         bytes32 overrideInitCodeHash = Eip7702Support._getEip7702InitCodeHashOverride(userOp);
-      26            0 :         return
-      27            0 :             _hashTypedDataSansChainId(ep, UserOperationLib.hash(userOp, overrideInitCodeHash));
-      28              :     }
-      29              :     
-      30              :     /// @dev Variant of `_hashTypedData` that excludes the chain ID.
-      31              :     /// Included for the niche use case of cross-chain workflows.
-      32            0 :     function _hashTypedDataSansChainId(address addr, bytes32 structHash)
-      33              :         internal
-      34              :         view
-      35              :         returns (bytes32 digest)
-      36              :     {
-      37            0 :         (,string memory name, string memory version, , , , ) = IERC5267(addr).eip712Domain();
-      38              :         /// @solidity memory-safe-assembly
-      39              :         assembly {
-      40            0 :             let m := mload(0x40) // Load the free memory pointer.
-      41            0 :             mstore(0x00, _DOMAIN_TYPEHASH_SANS_CHAIN_ID)
-      42            0 :             mstore(0x20, keccak256(add(name, 0x20), mload(name)))
-      43            0 :             mstore(0x40, keccak256(add(version, 0x20), mload(version)))
-      44            0 :             mstore(0x60, addr)
-      45              :             // Compute the digest.
-      46            0 :             mstore(0x20, keccak256(0x00, 0x80)) // Store the domain separator.
-      47            0 :             mstore(0x00, 0x1901) // Store "\x19\x01".
-      48            0 :             mstore(0x40, structHash) // Store the struct hash.
-      49            0 :             digest := keccak256(0x1e, 0x42)
-      50            0 :             mstore(0x40, m) // Restore the free memory pointer.
-      51            0 :             mstore(0x60, 0) // Restore the zero pointer.
-      52              :         }
-      53              :     }
-      54              : }
-        
-
-
- - - - -
Generated by: LCOV version 2.1-1
-
- - - diff --git a/coverage/src/core/ExecutionManager.sol.func-c.html b/coverage/src/core/ExecutionManager.sol.func-c.html deleted file mode 100644 index cf5c05ac..00000000 --- a/coverage/src/core/ExecutionManager.sol.func-c.html +++ /dev/null @@ -1,131 +0,0 @@ - - - - - - - LCOV - lcov.info - src/core/ExecutionManager.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/core - ExecutionManager.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:95.9 %4947
Test Date:2025-05-22 05:44:20Functions:100.0 %88
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by function hit count
ExecutionManager._onRevertSilent3
ExecutionManager._onRevertThrow3
ExecutionManager._delegateCall4
ExecutionManager._executeBatchCall4
ExecutionManager._executeCall4
ExecutionManager._executeDelegateCall4
ExecutionManager._call12
ExecutionManager._execute12
-
-
- - - -
Generated by: LCOV version 2.1-1
-
- - - diff --git a/coverage/src/core/ExecutionManager.sol.func.html b/coverage/src/core/ExecutionManager.sol.func.html deleted file mode 100644 index 6f09280e..00000000 --- a/coverage/src/core/ExecutionManager.sol.func.html +++ /dev/null @@ -1,131 +0,0 @@ - - - - - - - LCOV - lcov.info - src/core/ExecutionManager.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/core - ExecutionManager.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:95.9 %4947
Test Date:2025-05-22 05:44:20Functions:100.0 %88
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by function hit count
ExecutionManager._call12
ExecutionManager._delegateCall4
ExecutionManager._execute12
ExecutionManager._executeBatchCall4
ExecutionManager._executeCall4
ExecutionManager._executeDelegateCall4
ExecutionManager._onRevertSilent3
ExecutionManager._onRevertThrow3
-
-
- - - -
Generated by: LCOV version 2.1-1
-
- - - diff --git a/coverage/src/core/ExecutionManager.sol.gcov.html b/coverage/src/core/ExecutionManager.sol.gcov.html deleted file mode 100644 index 6119648e..00000000 --- a/coverage/src/core/ExecutionManager.sol.gcov.html +++ /dev/null @@ -1,168 +0,0 @@ - - - - - - - LCOV - lcov.info - src/core/ExecutionManager.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/core - ExecutionManager.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:95.9 %4947
Test Date:2025-05-22 05:44:20Functions:100.0 %88
-
- - - - - - - - -

-
            Line data    Source code
-
-       1              : pragma solidity ^0.8.0;
-       2              : 
-       3              : import {LibERC7579} from "solady/accounts/LibERC7579.sol";
-       4              : import "../types/Error.sol";
-       5              : 
-       6              : abstract contract ExecutionManager {
-       7           12 :     function _execute(bytes32 mode, bytes calldata executionData) internal {
-       8           12 :         bytes1 callType = LibERC7579.getCallType(mode);
-       9           12 :         bytes1 execType = LibERC7579.getExecType(mode);
-      10           12 :         function() onRevert;
-      11           12 :         if(execType == LibERC7579.EXECTYPE_DEFAULT) {
-      12            9 :             onRevert = _onRevertThrow;
-      13            3 :         } else if(execType == LibERC7579.EXECTYPE_TRY) {
-      14            3 :             onRevert = _onRevertSilent;
-      15              :         } else {
-      16            0 :             revert NotSupportedExecType();
-      17              :         }
-      18              : 
-      19           12 :         function(bytes calldata, function()) executeFunction;
-      20           12 :         if(callType == LibERC7579.CALLTYPE_SINGLE) {
-      21            4 :             executeFunction = _executeCall;
-      22            8 :         } else if(callType == LibERC7579.CALLTYPE_BATCH) {
-      23            4 :             executeFunction = _executeBatchCall;
-      24            4 :         } else if(callType == LibERC7579.CALLTYPE_DELEGATECALL) {
-      25            4 :             executeFunction = _executeDelegateCall;
-      26              :         } else {
-      27            0 :             revert NotSupportedCallType();
-      28              :         }
-      29           12 :         executeFunction(executionData, onRevert);
-      30              :     }
-      31              : 
-      32            4 :     function _executeCall(bytes calldata executionData, function() onRevert) internal {
-      33            4 :         (address target, uint256 value, bytes calldata data) = LibERC7579.decodeSingle(executionData);
-      34            4 :         bool success = _call(target, value, data);
-      35            4 :         if(!success) {
-      36            2 :             onRevert();
-      37              :         }
-      38              :     }
-      39              : 
-      40            4 :     function _executeDelegateCall(bytes calldata executionData, function() onRevert) internal {
-      41            4 :         (address delegate, bytes calldata data) = LibERC7579.decodeDelegate(executionData);
-      42            4 :         bool success = _delegateCall(delegate, data);
-      43            4 :         if(!success) {
-      44            2 :             onRevert();
-      45              :         }
-      46              :     }
-      47              : 
-      48            4 :     function _executeBatchCall(bytes calldata executionData, function() onRevert) internal {
-      49            4 :         bytes32[] calldata pointers = LibERC7579.decodeBatch(executionData);
-      50            4 :         uint256 length = pointers.length;
-      51            4 :         bytes[] memory result = new bytes[](length);
-      52              :         unchecked {
-      53            4 :             for (uint256 i; i < length; i++) {
-      54            8 :                 (address target, uint256 value, bytes calldata data) = LibERC7579.getExecution(pointers, i);
-      55            8 :                 bool success = _call(target, value, data);
-      56            8 :                 if(!success) {
-      57            2 :                     onRevert();
-      58              :                 }
-      59              :             }
-      60              :         }
-      61              :     }
-      62              : 
-      63            3 :     function _onRevertThrow() internal {
-      64              :         assembly {
-      65              :             // Bubble up the revert if the call reverts.
-      66            3 :             returndatacopy(0x00, 0x00, returndatasize())
-      67            3 :             revert(0x00, returndatasize())
-      68              :         }
-      69              :     }
-      70              : 
-      71            3 :     function _onRevertSilent() internal {
-      72              :     }
-      73              : 
-      74           12 :     function _call(address target, uint256 value, bytes calldata callData) internal returns(bool success){
-      75              :         /// @solidity memory-safe-assembly
-      76              :         assembly {
-      77           12 :             let ptr := mload(0x40)
-      78           12 :             calldatacopy(ptr, callData.offset, callData.length)
-      79           12 :             success := call(gas(), target, value, ptr, callData.length, codesize(), 0x00)
-      80              :         }
-      81              :     }
-      82              : 
-      83            4 :     function _delegateCall(address delegate, bytes calldata callData) internal returns(bool success){
-      84              :         /// @solidity memory-safe-assembly
-      85              :         assembly {
-      86            4 :             let ptr := mload(0x40)
-      87            4 :             calldatacopy(ptr, callData.offset, callData.length)
-      88              :             // Forwards the `data` to `delegate` via delegatecall.
-      89            4 :             success := delegatecall(gas(), delegate, ptr, callData.length, codesize(), 0x00)
-      90              :         }
-      91              :     }
-      92              : }
-        
-
-
- - - - -
Generated by: LCOV version 2.1-1
-
- - - diff --git a/coverage/src/core/ExecutorManager.sol.func-c.html b/coverage/src/core/ExecutorManager.sol.func-c.html deleted file mode 100644 index 96e08063..00000000 --- a/coverage/src/core/ExecutorManager.sol.func-c.html +++ /dev/null @@ -1,110 +0,0 @@ - - - - - - - LCOV - lcov.info - src/core/ExecutorManager.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/core - ExecutorManager.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:69.2 %139
Test Date:2025-05-22 05:44:20Functions:60.0 %53
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by function hit count
ExecutorManager._uninstallExecutor0
ExecutorManager.executorConfig0
ExecutorManager._installExecutor14
ExecutorManager._executorConfig17
ExecutorManager._executorStorage17
-
-
- - - -
Generated by: LCOV version 2.1-1
-
- - - diff --git a/coverage/src/core/ExecutorManager.sol.func.html b/coverage/src/core/ExecutorManager.sol.func.html deleted file mode 100644 index 92617d23..00000000 --- a/coverage/src/core/ExecutorManager.sol.func.html +++ /dev/null @@ -1,110 +0,0 @@ - - - - - - - LCOV - lcov.info - src/core/ExecutorManager.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/core - ExecutorManager.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:69.2 %139
Test Date:2025-05-22 05:44:20Functions:60.0 %53
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by function hit count
ExecutorManager._executorConfig17
ExecutorManager._executorStorage17
ExecutorManager._installExecutor14
ExecutorManager._uninstallExecutor0
ExecutorManager.executorConfig0
-
-
- - - -
Generated by: LCOV version 2.1-1
-
- - - diff --git a/coverage/src/core/ExecutorManager.sol.gcov.html b/coverage/src/core/ExecutorManager.sol.gcov.html deleted file mode 100644 index 4ef72290..00000000 --- a/coverage/src/core/ExecutorManager.sol.gcov.html +++ /dev/null @@ -1,119 +0,0 @@ - - - - - - - LCOV - lcov.info - src/core/ExecutorManager.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/core - ExecutorManager.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:69.2 %139
Test Date:2025-05-22 05:44:20Functions:60.0 %53
-
- - - - - - - - -

-
            Line data    Source code
-
-       1              : pragma solidity ^0.8.0;
-       2              : 
-       3              : import "../types/Types.sol";
-       4              : import "../types/Constants.sol";
-       5              : import "../interfaces/IERC7579Modules.sol";
-       6              : 
-       7              : contract ExecutorManager {
-       8              :     error NotExecutor();
-       9              :     struct ExecutorConfig {
-      10              :         IHook hook; // address(1) : hook not required, address(0) : validator not installed
-      11              :     }
-      12              : 
-      13              :     struct ExecutorStorage {
-      14              :         mapping(IExecutor => ExecutorConfig) executorConfig;
-      15              :     }
-      16              : 
-      17           17 :     function _executorStorage() internal view returns (ExecutorStorage storage $) {
-      18              :         assembly {
-      19           17 :             $.slot := EXECUTOR_MANAGER_STORAGE_SLOT
-      20              :         }
-      21              :     }
-      22              : 
-      23            0 :     function executorConfig(IExecutor executor) external view returns (ExecutorConfig memory) {
-      24            0 :         return _executorConfig(executor);
-      25              :     }
-      26              : 
-      27           17 :     function _executorConfig(IExecutor executor) internal view returns (ExecutorConfig storage config) {
-      28           17 :         config = _executorStorage().executorConfig[executor];
-      29              :     }
-      30              : 
-      31           14 :     function _installExecutor(address _executor, bytes calldata _internalData, bool _installSuccess) internal {
-      32              :         // NOTE: we don't care if install was successful 
-      33           14 :         address hook = _internalData.length >= 20 ? address(bytes20(_internalData[0:20])) : address(0);
-      34           14 :         if(hook == address(0)) {
-      35           14 :             hook = address(1); // address(1) indicates it is installed and does not require any hook
-      36              :         }
-      37           14 :         _executorConfig(IExecutor(_executor)).hook = IHook(hook);
-      38              :     }
-      39              : 
-      40            0 :     function _uninstallExecutor(address _executor, bytes calldata _internalData, bool _installSuccess) internal {
-      41            0 :         _executorConfig(IExecutor(_executor)).hook = IHook(address(0));
-      42              :     }
-      43              : }
-        
-
-
- - - - -
Generated by: LCOV version 2.1-1
-
- - - diff --git a/coverage/src/core/HookManager.sol.func-c.html b/coverage/src/core/HookManager.sol.func-c.html deleted file mode 100644 index 7f44cd61..00000000 --- a/coverage/src/core/HookManager.sol.func-c.html +++ /dev/null @@ -1,103 +0,0 @@ - - - - - - - LCOV - lcov.info - src/core/HookManager.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/core - HookManager.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:45.5 %115
Test Date:2025-05-22 05:44:20Functions:50.0 %42
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by function hit count
HookManager._installHook0
HookManager._uninstallHook0
HookManager._postHook3
HookManager._preHook3
-
-
- - - -
Generated by: LCOV version 2.1-1
-
- - - diff --git a/coverage/src/core/HookManager.sol.func.html b/coverage/src/core/HookManager.sol.func.html deleted file mode 100644 index f7d8c7a7..00000000 --- a/coverage/src/core/HookManager.sol.func.html +++ /dev/null @@ -1,103 +0,0 @@ - - - - - - - LCOV - lcov.info - src/core/HookManager.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/core - HookManager.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:45.5 %115
Test Date:2025-05-22 05:44:20Functions:50.0 %42
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by function hit count
HookManager._installHook0
HookManager._postHook3
HookManager._preHook3
HookManager._uninstallHook0
-
-
- - - -
Generated by: LCOV version 2.1-1
-
- - - diff --git a/coverage/src/core/HookManager.sol.gcov.html b/coverage/src/core/HookManager.sol.gcov.html deleted file mode 100644 index b32210cd..00000000 --- a/coverage/src/core/HookManager.sol.gcov.html +++ /dev/null @@ -1,113 +0,0 @@ - - - - - - - LCOV - lcov.info - src/core/HookManager.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/core - HookManager.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:45.5 %115
Test Date:2025-05-22 05:44:20Functions:50.0 %42
-
- - - - - - - - -

-
            Line data    Source code
-
-       1              : pragma solidity ^0.8.0;
-       2              : 
-       3              : import {IHook, IFallback, IModule} from "../interfaces/IERC7579Modules.sol";
-       4              : import {CallType} from "../types/Types.sol";
-       5              : import {
-       6              :     SELECTOR_MANAGER_STORAGE_SLOT,
-       7              :     CALLTYPE_DELEGATECALL,
-       8              :     CALLTYPE_SINGLE,
-       9              :     MODULE_TYPE_FALLBACK
-      10              : } from "../types/Constants.sol";
-      11              : import "../types/Error.sol";
-      12              : 
-      13              : abstract contract HookManager {
-      14            0 :     function _installHook(address _hook, bytes calldata _internalData, bool _installSuccess) internal {
-      15            0 :         if(_internalData.length == 0) {
-      16            0 :             require(_installSuccess, ModuleInstallFailed());
-      17              :         }
-      18              :     }
-      19              : 
-      20            0 :     function _uninstallHook(address _hook, bytes calldata _internalData, bool _uninstallSuccess) internal {
-      21              :         // no-op
-      22              :     }
-      23              : 
-      24            3 :     function _preHook(IHook _hook) internal returns(bytes memory context){
-      25            3 :         require(address(_hook) != address(0), NotInstalled());
-      26            3 :         if(address(_hook) != address(1)) {
-      27            0 :             context = _hook.preCheck(msg.sender, msg.value, msg.data);
-      28              :         }
-      29              :     }
-      30            3 :     function _postHook(IHook _hook, bytes memory context) internal {
-      31              :         // bool success,
-      32              :         // bytes memory result
-      33            3 :         if(address(_hook) != address(1)) {
-      34            0 :             _hook.postCheck(context);
-      35              :         }
-      36              :     }
-      37              : }
-        
-
-
- - - - -
Generated by: LCOV version 2.1-1
-
- - - diff --git a/coverage/src/core/ModuleManager.sol.func-c.html b/coverage/src/core/ModuleManager.sol.func-c.html deleted file mode 100644 index 2cda5175..00000000 --- a/coverage/src/core/ModuleManager.sol.func-c.html +++ /dev/null @@ -1,117 +0,0 @@ - - - - - - - LCOV - lcov.info - src/core/ModuleManager.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/core - ModuleManager.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:38.5 %3915
Test Date:2025-05-22 05:44:20Functions:50.0 %63
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by function hit count
ModuleManager._initialized0
ModuleManager._installHash0
ModuleManager._uninstall0
ModuleManager.onlyExecutor3
ModuleManager._install15
ModuleManager._installModule15
-
-
- - - -
Generated by: LCOV version 2.1-1
-
- - - diff --git a/coverage/src/core/ModuleManager.sol.func.html b/coverage/src/core/ModuleManager.sol.func.html deleted file mode 100644 index 4234851d..00000000 --- a/coverage/src/core/ModuleManager.sol.func.html +++ /dev/null @@ -1,117 +0,0 @@ - - - - - - - LCOV - lcov.info - src/core/ModuleManager.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/core - ModuleManager.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:38.5 %3915
Test Date:2025-05-22 05:44:20Functions:50.0 %63
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by function hit count
ModuleManager._initialized0
ModuleManager._install15
ModuleManager._installHash0
ModuleManager._installModule15
ModuleManager._uninstall0
ModuleManager.onlyExecutor3
-
-
- - - -
Generated by: LCOV version 2.1-1
-
- - - diff --git a/coverage/src/core/ModuleManager.sol.gcov.html b/coverage/src/core/ModuleManager.sol.gcov.html deleted file mode 100644 index df5096d6..00000000 --- a/coverage/src/core/ModuleManager.sol.gcov.html +++ /dev/null @@ -1,173 +0,0 @@ - - - - - - - LCOV - lcov.info - src/core/ModuleManager.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/core - ModuleManager.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:38.5 %3915
Test Date:2025-05-22 05:44:20Functions:50.0 %63
-
- - - - - - - - -

-
            Line data    Source code
-
-       1              : pragma solidity ^0.8.0;
-       2              : 
-       3              : import "../interfaces/IERC7579Modules.sol";
-       4              : import {ValidationManager} from "./ValidationManager.sol";
-       5              : import {ExecutorManager} from "./ExecutorManager.sol";
-       6              : import {HookManager} from "./HookManager.sol";
-       7              : import {SelectorManager} from "./SelectorManager.sol";
-       8              : import "../types/Error.sol";
-       9              : import "../types/Events.sol";
-      10              : import "../types/Structs.sol";
-      11              : import "../types/Types.sol";
-      12              : 
-      13              : 
-      14              : function calldataKeccak(bytes calldata data) pure returns (bytes32 ret) {
-      15              :     assembly ("memory-safe") {
-      16              :         let mem := mload(0x40)
-      17              :         let len := data.length
-      18              :         calldatacopy(mem, data.offset, len)
-      19              :         ret := keccak256(mem, len)
-      20              :     }
-      21              : }
-      22              : 
-      23              : contract ModuleManager is ValidationManager, ExecutorManager, HookManager, SelectorManager {
-      24            3 :     modifier onlyExecutor {
-      25            3 :         IHook hook = _executorConfig(IExecutor(msg.sender)).hook;
-      26            3 :         bytes memory hookData = _preHook(hook);
-      27              :         _;
-      28            3 :         _postHook(hook, hookData);
-      29              :     }
-      30              : 
-      31            0 :     function _initialized() internal view returns(bool) {
-      32            0 :         return bytes3(address(this).code) == bytes3(0xef0100) || ValidationId.unwrap(_validationStorage().root) != bytes20(0);
-      33              :     }
-      34              : 
-      35            0 :     function _installHash(Install[] calldata packages) internal pure returns (bytes32) {
-      36            0 :         bytes32[] memory packageHashes = new bytes32[](packages.length);
-      37            0 :         for (uint256 i = 0; i < packages.length; i++) {
-      38            0 :             Install calldata pkg = packages[i];
-      39            0 :             packageHashes[i] = keccak256(
-      40              :                 abi.encode(pkg.moduleType, pkg.module, calldataKeccak(pkg.moduleData), calldataKeccak(pkg.internalData))
-      41              :             );
-      42              :         }
-      43            0 :         return keccak256(abi.encodePacked(packageHashes));
-      44              :     }
-      45              : 
-      46           15 :     function _installModule(uint256 moduleType, address module, bytes calldata moduleData, bytes calldata internalData)
-      47              :         internal
-      48              :     {
-      49           15 :         function(address, bytes calldata, bool) hook;
-      50           15 :         if (moduleType == 1) {
-      51            1 :             hook = _installValidator;
-      52           14 :         } else if(moduleType == 2) {
-      53           14 :             hook = _installExecutor;
-      54            0 :         } else if(moduleType == 3) {
-      55            0 :             hook = _installSelector;
-      56            0 :         } else if(moduleType == 4) {
-      57            0 :             hook = _installHook;
-      58            0 :         } else if(moduleType == 5) {
-      59            0 :             hook = _installPolicy;
-      60            0 :         } else if(moduleType == 6) {
-      61            0 :             hook = _installSigner;
-      62              :         } else {
-      63            0 :             revert NotImplemented();
-      64              :         }
-      65           15 :         _install(module, moduleData, internalData, hook);
-      66           15 :         emit ModuleInstalled(moduleType, module);
-      67              :     }
-      68              : 
-      69            0 :     function _install(Install[] calldata packages) internal {
-      70            0 :         for (uint256 i = 0; i < packages.length; i++) {
-      71            0 :             Install calldata pkg = packages[i];
-      72            0 :             _installModule(pkg.moduleType, pkg.module, pkg.moduleData, pkg.internalData);
-      73              :         }
-      74              :     }
-      75              : 
-      76           15 :     function _install(
-      77              :         address module,
-      78              :         bytes calldata data,
-      79              :         bytes calldata internalData,
-      80              :         function(address, bytes calldata, bool) hook
-      81              :     ) internal {
-      82           15 :         (bool success,) = module.call(abi.encodeWithSelector(IModule.onInstall.selector, data));
-      83           15 :         hook(module, internalData, success);
-      84              :     }
-      85              : 
-      86            0 :     function _uninstall(
-      87              :         address module,
-      88              :         bytes calldata data,
-      89              :         bytes calldata internalData,
-      90              :         function(address, bytes calldata, bool) hook
-      91              :     ) internal {
-      92              :         // TODO: make sure we use extra safe call
-      93            0 :         (bool success,) = module.call(abi.encodeWithSelector(IModule.onUninstall.selector, data));
-      94            0 :         hook(module, internalData, success);
-      95              :     }
-      96              : 
-      97              : }
-        
-
-
- - - - -
Generated by: LCOV version 2.1-1
-
- - - diff --git a/coverage/src/core/SelectorManager.sol.func-c.html b/coverage/src/core/SelectorManager.sol.func-c.html deleted file mode 100644 index bf293a82..00000000 --- a/coverage/src/core/SelectorManager.sol.func-c.html +++ /dev/null @@ -1,103 +0,0 @@ - - - - - - - LCOV - lcov.info - src/core/SelectorManager.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/core - SelectorManager.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:0.0 %160
Test Date:2025-05-22 05:44:20Functions:0.0 %40
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by function hit count
SelectorManager._installSelector0
SelectorManager._selectorConfig0
SelectorManager._selectorStorage0
SelectorManager.selectorConfig0
-
-
- - - -
Generated by: LCOV version 2.1-1
-
- - - diff --git a/coverage/src/core/SelectorManager.sol.func.html b/coverage/src/core/SelectorManager.sol.func.html deleted file mode 100644 index 865911d0..00000000 --- a/coverage/src/core/SelectorManager.sol.func.html +++ /dev/null @@ -1,103 +0,0 @@ - - - - - - - LCOV - lcov.info - src/core/SelectorManager.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/core - SelectorManager.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:0.0 %160
Test Date:2025-05-22 05:44:20Functions:0.0 %40
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by function hit count
SelectorManager._installSelector0
SelectorManager._selectorConfig0
SelectorManager._selectorStorage0
SelectorManager.selectorConfig0
-
-
- - - -
Generated by: LCOV version 2.1-1
-
- - - diff --git a/coverage/src/core/SelectorManager.sol.gcov.html b/coverage/src/core/SelectorManager.sol.gcov.html deleted file mode 100644 index 61307ca8..00000000 --- a/coverage/src/core/SelectorManager.sol.gcov.html +++ /dev/null @@ -1,127 +0,0 @@ - - - - - - - LCOV - lcov.info - src/core/SelectorManager.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/core - SelectorManager.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:0.0 %160
Test Date:2025-05-22 05:44:20Functions:0.0 %40
-
- - - - - - - - -

-
            Line data    Source code
-
-       1              : // SPDX-License-Identifier: MIT
-       2              : pragma solidity ^0.8.0;
-       3              : 
-       4              : import {IHook, IFallback, IModule} from "../interfaces/IERC7579Modules.sol";
-       5              : import {CallType} from "../types/Types.sol";
-       6              : import {
-       7              :     SELECTOR_MANAGER_STORAGE_SLOT,
-       8              :     CALLTYPE_DELEGATECALL,
-       9              :     CALLTYPE_SINGLE,
-      10              :     MODULE_TYPE_FALLBACK
-      11              : } from "../types/Constants.sol";
-      12              : import "../types/Error.sol";
-      13              : 
-      14              : abstract contract SelectorManager {
-      15              : 
-      16              :     struct SelectorConfig {
-      17              :         IHook hook; // 20 bytes for hook address
-      18              :         address target; // 20 bytes target will be fallback module, called with call
-      19              :         CallType callType;
-      20              :     }
-      21              : 
-      22              :     struct SelectorStorage {
-      23              :         mapping(bytes4 => SelectorConfig) selectorConfig;
-      24              :     }
-      25              : 
-      26            0 :     function selectorConfig(bytes4 selector) external view returns (SelectorConfig memory) {
-      27            0 :         return _selectorConfig(selector);
-      28              :     }
-      29              : 
-      30            0 :     function _selectorConfig(bytes4 selector) internal view returns (SelectorConfig storage config) {
-      31            0 :         config = _selectorStorage().selectorConfig[selector];
-      32              :     }
-      33              : 
-      34            0 :     function _selectorStorage() internal pure returns (SelectorStorage storage ss) {
-      35            0 :         bytes32 slot = SELECTOR_MANAGER_STORAGE_SLOT;
-      36              :         assembly {
-      37            0 :             ss.slot := slot
-      38              :         }
-      39              :     }
-      40              : 
-      41            0 :     function _installSelector(address _module, bytes calldata _internalData, bool _installSuccess) internal {
-      42            0 :         CallType callType = CallType.wrap(bytes1(_internalData[4]));
-      43            0 :         require(callType == CALLTYPE_DELEGATECALL || _installSuccess, ModuleInstallFailed());
-      44            0 :         bytes4 selector = bytes4(_internalData[0:4]);
-      45            0 :         address hook = address(bytes20(_internalData[5:25]));
-      46            0 :         SelectorConfig storage $ = _selectorConfig(selector);
-      47            0 :         $.target = _module;
-      48            0 :         $.callType = callType;
-      49            0 :         $.hook = IHook(hook);
-      50              :     }
-      51              : }
-        
-
-
- - - - -
Generated by: LCOV version 2.1-1
-
- - - diff --git a/coverage/src/core/ValidationManager.sol.func-c.html b/coverage/src/core/ValidationManager.sol.func-c.html deleted file mode 100644 index 53b4a84f..00000000 --- a/coverage/src/core/ValidationManager.sol.func-c.html +++ /dev/null @@ -1,166 +0,0 @@ - - - - - - - LCOV - lcov.info - src/core/ValidationManager.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/core - ValidationManager.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:9.2 %656
Test Date:2025-05-22 05:44:20Functions:15.4 %132
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by function hit count
ValidationManager._checkValidation0
ValidationManager._installPolicy0
ValidationManager._installSigner0
ValidationManager._parseNonce0
ValidationManager._setRoot0
ValidationManager._uninstallPolicy0
ValidationManager._uninstallSigner0
ValidationManager._uninstallValidator0
ValidationManager._validateUserOp0
ValidationManager._verify7702Signature0
ValidationManager._verifySignature0
ValidationManager._installValidator1
ValidationManager._validationStorage1
-
-
- - - -
Generated by: LCOV version 2.1-1
-
- - - diff --git a/coverage/src/core/ValidationManager.sol.func.html b/coverage/src/core/ValidationManager.sol.func.html deleted file mode 100644 index a5b52db3..00000000 --- a/coverage/src/core/ValidationManager.sol.func.html +++ /dev/null @@ -1,166 +0,0 @@ - - - - - - - LCOV - lcov.info - src/core/ValidationManager.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/core - ValidationManager.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:9.2 %656
Test Date:2025-05-22 05:44:20Functions:15.4 %132
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by function hit count
ValidationManager._checkValidation0
ValidationManager._installPolicy0
ValidationManager._installSigner0
ValidationManager._installValidator1
ValidationManager._parseNonce0
ValidationManager._setRoot0
ValidationManager._uninstallPolicy0
ValidationManager._uninstallSigner0
ValidationManager._uninstallValidator0
ValidationManager._validateUserOp0
ValidationManager._validationStorage1
ValidationManager._verify7702Signature0
ValidationManager._verifySignature0
-
-
- - - -
Generated by: LCOV version 2.1-1
-
- - - diff --git a/coverage/src/core/ValidationManager.sol.gcov.html b/coverage/src/core/ValidationManager.sol.gcov.html deleted file mode 100644 index 2a13e66f..00000000 --- a/coverage/src/core/ValidationManager.sol.gcov.html +++ /dev/null @@ -1,240 +0,0 @@ - - - - - - - LCOV - lcov.info - src/core/ValidationManager.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/core - ValidationManager.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:9.2 %656
Test Date:2025-05-22 05:44:20Functions:15.4 %132
-
- - - - - - - - -

-
            Line data    Source code
-
-       1              : pragma solidity ^0.8.0;
-       2              : 
-       3              : import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol";
-       4              : import "../interfaces/IERC7579Modules.sol";
-       5              : import "../types/Error.sol";
-       6              : import "../types/Types.sol";
-       7              : import "../types/Constants.sol";
-       8              : import "../types/Structs.sol";
-       9              : import {ECDSA} from "solady/utils/ECDSA.sol";
-      10              : 
-      11              : struct ValidationInfo {
-      12              :     ValidationType vType;
-      13              :     address[] policies;
-      14              :     address signer;
-      15              :     bytes4 group;
-      16              : }
-      17              : 
-      18              : struct ValidationGroupInfo {
-      19              :     mapping(bytes4 selector => bool) allowed;
-      20              :     bytes32 permission;
-      21              : }
-      22              : 
-      23              : struct ValidationStorage {
-      24              :     ValidationId root;
-      25              :     mapping(ValidationId vId => ValidationInfo) vInfo;
-      26              :     mapping(bytes4 group => ValidationGroupInfo) gInfo;
-      27              : }
-      28              : 
-      29              : function getValidator(ValidationId vId) pure returns (address v) {
-      30              :     assembly {
-      31              :         v := shr(96, vId)
-      32              :     }
-      33              : }
-      34              : 
-      35              : function getType(ValidationId validator) pure returns (ValidationType vType) {
-      36              :     assembly {
-      37              :         vType := validator
-      38              :     }
-      39              : }
-      40              : 
-      41              : abstract contract ValidationManager {
-      42              :     ValidationId transient installingPermission;
-      43              : 
-      44            1 :     function _validationStorage() internal view returns (ValidationStorage storage $) {
-      45              :         assembly {
-      46            1 :             $.slot := VALIDATION_MANAGER_STORAGE_SLOT
-      47              :         }
-      48              :     }
-      49              : 
-      50            1 :     function _installValidator(address _validator, bytes calldata _internalData, bool _installSuccess) internal {
-      51            1 :         require(_installSuccess, ModuleInstallFailed());
-      52            1 :         ValidationStorage storage $ = _validationStorage();
-      53            1 :         $.vInfo[ValidationId.wrap(bytes20(_validator))].vType = VALIDATION_TYPE_VALIDATOR;
-      54              :     }
-      55              : 
-      56            0 :     function _uninstallValidator(address _validator, bytes calldata _internalData, bool _uninstallSuccess)
-      57              :         internal
-      58              :     {
-      59            0 :         ValidationStorage storage $ = _validationStorage();
-      60            0 :         $.vInfo[ValidationId.wrap(bytes20(_validator))].vType = VALIDATION_TYPE_VALIDATOR;
-      61              :     }
-      62              : 
-      63            0 :     function _installPolicy(address _policy, bytes calldata _internalData, bool _installSuccess) internal {
-      64            0 :         require(_installSuccess, ModuleInstallFailed());
-      65            0 :         ValidationStorage storage $ = _validationStorage();
-      66            0 :         ValidationId vId = ValidationId.wrap(bytes20(_internalData[0:20]));
-      67            0 :         if(installingPermission == ValidationId.wrap(bytes20(0))) {
-      68            0 :             require(vId != ValidationId.wrap(bytes20(0)), "invalid validationId");
-      69            0 :             installingPermission = ValidationId.wrap(bytes20(_internalData[0:20]));
-      70            0 :             $.vInfo[vId].vType = VALIDATION_TYPE_PERMISSION;
-      71              :         } else {
-      72            0 :             require(installingPermission == vId, "permissionId should be consistent");
-      73              :         }
-      74            0 :         $.vInfo[vId].policies.push(_policy);
-      75              :     }
-      76              : 
-      77            0 :     function _uninstallPolicy(address _policy, bytes calldata _internalData, bool _uninstallSuccess) internal {
-      78              :     }
-      79              : 
-      80            0 :     function _installSigner(address _signer, bytes calldata _internalData, bool _installSuccess) internal {
-      81            0 :         require(_installSuccess, ModuleInstallFailed());
-      82            0 :         ValidationStorage storage $ = _validationStorage();
-      83            0 :         ValidationId vId = ValidationId.wrap(bytes20(_internalData[0:20]));
-      84            0 :         if(installingPermission == ValidationId.wrap(bytes20(0))) {
-      85            0 :             require(vId != ValidationId.wrap(bytes20(0)), "invalid validationId");
-      86            0 :             require($.vInfo[vId].vType == ValidationType.wrap(0x00), "already taken");
-      87            0 :             installingPermission = ValidationId.wrap(bytes20(_internalData[0:20]));
-      88            0 :             $.vInfo[vId].vType = VALIDATION_TYPE_PERMISSION;
-      89              :         } else {
-      90            0 :             require(installingPermission == vId, "permissionId should be consistent");
-      91              :         }
-      92            0 :         $.vInfo[vId].signer = _signer;
-      93              : 
-      94            0 :         installingPermission = ValidationId.wrap(bytes20(0));
-      95              :     }
-      96              : 
-      97            0 :     function _uninstallSigner(address _signer, bytes calldata _internalData, bool _uninstallSuccess) internal {
-      98              :     }
-      99              : 
-     100            0 :     function _checkValidation(ValidationMode vMode, ValidationType vType, ValidationId vId) internal view {
-     101            0 :         ValidationStorage storage $ = _validationStorage();
-     102            0 :         ValidationId v;
-     103            0 :         if (vType == VALIDATION_TYPE_ROOT) {
-     104            0 :             v = $.root;
-     105              :         } else {
-     106            0 :             v = vId;
-     107            0 :             require($.vInfo[vId].vType == vType, InvalidValidator());
-     108              :         }
-     109              :     }
-     110              : 
-     111            0 :     function _parseNonce(uint256 nonce)
-     112              :         internal
-     113              :         pure
-     114              :         returns (ValidationMode vMode, ValidationType vType, ValidationId vId)
-     115              :     {
-     116              :         // 2bytes mode (1byte currentMode, 1byte type)
-     117              :         // 20bytes identifier
-     118              :         // 1byte mode  | 1byte type | 20bytes vId | 2byte nonceKey | 8byte nonce == 32bytes
-     119              :         assembly {
-     120            0 :             vMode := nonce
-     121            0 :             vType := shl(8, nonce)
-     122            0 :             vId := shl(16, nonce)
-     123              :         }
-     124              :     }
-     125              : 
-     126            0 :     function _verifySignature(ValidationId vId, address requester, bytes32 _hash, bytes calldata _signature)
-     127              :         internal
-     128              :         view
-     129              :         returns (uint256 validationData)
-     130              :     {
-     131            0 :         if(ValidationId.unwrap(vId) == bytes20(0)) {
-     132            0 :             return _verify7702Signature(_hash, _signature) ? 0 : 1;
-     133              :         }
-     134            0 :         IValidator validator = IValidator(getValidator(vId)); // TODO: add permission support;
-     135            0 :         validator.isValidSignatureWithSender(requester, /*NOTE: fix this */ _hash, _signature);
-     136              :     }
-     137              : 
-     138            0 :     function _validateUserOp(ValidationId vId, bytes32 opHash, PackedUserOperation calldata op, bytes calldata userOpSignature) internal returns(uint256 validationData) {
-     139            0 :         if(ValidationId.unwrap(vId) == bytes20(0)) {
-     140            0 :             return _verify7702Signature(opHash, userOpSignature) ? 0 : 1;
-     141              :         }
-     142              :     }
-     143              : 
-     144            0 :     function _verify7702Signature(bytes32 hash, bytes calldata sig) internal view returns (bool) {
-     145            0 :         return ECDSA.recover(hash, sig) == address(this);
-     146              :     }
-     147              : 
-     148            0 :     function _setRoot(Install calldata pkg) internal {
-     149            0 :         ValidationId vId;
-     150            0 :         if(pkg.moduleType == 1) {
-     151            0 :             vId = ValidationId.wrap(bytes20(pkg.module));
-     152            0 :         } else if (pkg.moduleType == 5 || pkg.moduleType == 6) {
-     153            0 :             vId = ValidationId.wrap(bytes20(pkg.internalData[0:4]));
-     154              :         } else {
-     155            0 :             revert InvalidRootValidation();
-     156              :         }
-     157            0 :         _setRoot(vId);
-     158              :     }
-     159              : 
-     160            0 :     function _setRoot(ValidationId vId) internal {
-     161            0 :         ValidationStorage storage $ = _validationStorage();
-     162            0 :         $.root = vId;
-     163              :     }
-     164              : }
-        
-
-
- - - - -
Generated by: LCOV version 2.1-1
-
- - - diff --git a/coverage/src/core/index-sort-f.html b/coverage/src/core/index-sort-f.html deleted file mode 100644 index 6be470d1..00000000 --- a/coverage/src/core/index-sort-f.html +++ /dev/null @@ -1,165 +0,0 @@ - - - - - - - LCOV - lcov.info - src/core - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/coreCoverageTotalHit
Test:lcov.infoLines:42.5 %19382
Test Date:2025-05-22 05:44:20Functions:45.0 %4018
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

File Sort by file nameLine Coverage Sort by line coverageFunction Coverage Sort by function coverage
Rate Total Hit Rate Total Hit
SelectorManager.sol -
0.0%
-
0.0 %160.0 %4
ValidationManager.sol -
9.2%9.2%
-
9.2 %65615.4 %132
HookManager.sol -
45.5%45.5%
-
45.5 %11550.0 %42
ModuleManager.sol -
38.5%38.5%
-
38.5 %391550.0 %63
ExecutorManager.sol -
69.2%69.2%
-
69.2 %13960.0 %53
ExecutionManager.sol -
95.9%95.9%
-
95.9 %4947100.0 %88
-
-
- - - - -
Generated by: LCOV version 2.1-1
-
- - - diff --git a/coverage/src/core/index-sort-l.html b/coverage/src/core/index-sort-l.html deleted file mode 100644 index cee9d32c..00000000 --- a/coverage/src/core/index-sort-l.html +++ /dev/null @@ -1,165 +0,0 @@ - - - - - - - LCOV - lcov.info - src/core - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/coreCoverageTotalHit
Test:lcov.infoLines:42.5 %19382
Test Date:2025-05-22 05:44:20Functions:45.0 %4018
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

File Sort by file nameLine Coverage Sort by line coverageFunction Coverage Sort by function coverage
Rate Total Hit Rate Total Hit
SelectorManager.sol -
0.0%
-
0.0 %160.0 %4
ValidationManager.sol -
9.2%9.2%
-
9.2 %65615.4 %132
ModuleManager.sol -
38.5%38.5%
-
38.5 %391550.0 %63
HookManager.sol -
45.5%45.5%
-
45.5 %11550.0 %42
ExecutorManager.sol -
69.2%69.2%
-
69.2 %13960.0 %53
ExecutionManager.sol -
95.9%95.9%
-
95.9 %4947100.0 %88
-
-
- - - - -
Generated by: LCOV version 2.1-1
-
- - - diff --git a/coverage/src/core/index.html b/coverage/src/core/index.html deleted file mode 100644 index 8b73bcd8..00000000 --- a/coverage/src/core/index.html +++ /dev/null @@ -1,165 +0,0 @@ - - - - - - - LCOV - lcov.info - src/core - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/coreCoverageTotalHit
Test:lcov.infoLines:42.5 %19382
Test Date:2025-05-22 05:44:20Functions:45.0 %4018
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

File Sort by file nameLine Coverage Sort by line coverageFunction Coverage Sort by function coverage
Rate Total Hit Rate Total Hit
ExecutionManager.sol -
95.9%95.9%
-
95.9 %4947100.0 %88
ExecutorManager.sol -
69.2%69.2%
-
69.2 %13960.0 %53
HookManager.sol -
45.5%45.5%
-
45.5 %11550.0 %42
ModuleManager.sol -
38.5%38.5%
-
38.5 %391550.0 %63
SelectorManager.sol -
0.0%
-
0.0 %160.0 %4
ValidationManager.sol -
9.2%9.2%
-
9.2 %65615.4 %132
-
-
- - - - -
Generated by: LCOV version 2.1-1
-
- - - diff --git a/coverage/src/index-sort-f.html b/coverage/src/index-sort-f.html deleted file mode 100644 index 2584308a..00000000 --- a/coverage/src/index-sort-f.html +++ /dev/null @@ -1,129 +0,0 @@ - - - - - - - LCOV - lcov.info - src - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - srcCoverageTotalHit
Test:lcov.infoLines:19.2 %9919
Test Date:2025-05-22 05:44:20Functions:36.8 %197
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

File Sort by file nameLine Coverage Sort by line coverageFunction Coverage Sort by function coverage
Rate Total Hit Rate Total Hit
Lib4337.sol -
0.0%
-
0.0 %170.0 %2
Kernel.sol -
18.6%18.6%
-
18.6 %701335.7 %145
KernelFactory.sol -
50.0%50.0%
-
50.0 %12666.7 %32
-
-
- - - - -
Generated by: LCOV version 2.1-1
-
- - - diff --git a/coverage/src/index-sort-l.html b/coverage/src/index-sort-l.html deleted file mode 100644 index 0047260d..00000000 --- a/coverage/src/index-sort-l.html +++ /dev/null @@ -1,129 +0,0 @@ - - - - - - - LCOV - lcov.info - src - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - srcCoverageTotalHit
Test:lcov.infoLines:19.2 %9919
Test Date:2025-05-22 05:44:20Functions:36.8 %197
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

File Sort by file nameLine Coverage Sort by line coverageFunction Coverage Sort by function coverage
Rate Total Hit Rate Total Hit
Lib4337.sol -
0.0%
-
0.0 %170.0 %2
Kernel.sol -
18.6%18.6%
-
18.6 %701335.7 %145
KernelFactory.sol -
50.0%50.0%
-
50.0 %12666.7 %32
-
-
- - - - -
Generated by: LCOV version 2.1-1
-
- - - diff --git a/coverage/src/index.html b/coverage/src/index.html deleted file mode 100644 index 0d144bfd..00000000 --- a/coverage/src/index.html +++ /dev/null @@ -1,129 +0,0 @@ - - - - - - - LCOV - lcov.info - src - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - srcCoverageTotalHit
Test:lcov.infoLines:19.2 %9919
Test Date:2025-05-22 05:44:20Functions:36.8 %197
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

File Sort by file nameLine Coverage Sort by line coverageFunction Coverage Sort by function coverage
Rate Total Hit Rate Total Hit
Kernel.sol -
18.6%18.6%
-
18.6 %701335.7 %145
KernelFactory.sol -
50.0%50.0%
-
50.0 %12666.7 %32
Lib4337.sol -
0.0%
-
0.0 %170.0 %2
-
-
- - - - -
Generated by: LCOV version 2.1-1
-
- - - diff --git a/coverage/test/Kernel.t.sol.func-c.html b/coverage/test/Kernel.t.sol.func-c.html deleted file mode 100644 index 2f86a98d..00000000 --- a/coverage/test/Kernel.t.sol.func-c.html +++ /dev/null @@ -1,110 +0,0 @@ - - - - - - - LCOV - lcov.info - test/Kernel.t.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - test - Kernel.t.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:81.8 %119
Test Date:2025-05-22 05:44:20Functions:80.0 %54
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by function hit count
MockValidator.onUninstall0
MockValidator.onInstall1
MockCallee.lorem2
MockCallee.forceRevert6
MockCallee.foo8
-
-
- - - -
Generated by: LCOV version 2.1-1
-
- - - diff --git a/coverage/test/Kernel.t.sol.func.html b/coverage/test/Kernel.t.sol.func.html deleted file mode 100644 index 4d2d6ed7..00000000 --- a/coverage/test/Kernel.t.sol.func.html +++ /dev/null @@ -1,110 +0,0 @@ - - - - - - - LCOV - lcov.info - test/Kernel.t.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - test - Kernel.t.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:81.8 %119
Test Date:2025-05-22 05:44:20Functions:80.0 %54
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by function hit count
MockCallee.foo8
MockCallee.forceRevert6
MockCallee.lorem2
MockValidator.onInstall1
MockValidator.onUninstall0
-
-
- - - -
Generated by: LCOV version 2.1-1
-
- - - diff --git a/coverage/test/Kernel.t.sol.gcov.html b/coverage/test/Kernel.t.sol.gcov.html deleted file mode 100644 index 27124f0b..00000000 --- a/coverage/test/Kernel.t.sol.gcov.html +++ /dev/null @@ -1,284 +0,0 @@ - - - - - - - LCOV - lcov.info - test/Kernel.t.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - test - Kernel.t.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:81.8 %119
Test Date:2025-05-22 05:44:20Functions:80.0 %54
-
- - - - - - - - -

-
            Line data    Source code
-
-       1              : pragma solidity ^0.8.0;
-       2              : 
-       3              : import {Test} from "forge-std/Test.sol";
-       4              : import {EntryPointLib} from "./utils/EntryPointLib.sol";
-       5              : import {IEntryPoint} from "account-abstraction/interfaces/IEntryPoint.sol";
-       6              : import {Kernel} from "src/Kernel.sol";
-       7              : import {KernelFactory} from "src/KernelFactory.sol";
-       8              : import {LibERC7579} from "solady/accounts/LibERC7579.sol";
-       9              : 
-      10              : contract MockValidator {
-      11              :     event MockInstall(bytes data);
-      12              :     event MockUninstall(bytes data);
-      13              : 
-      14            1 :     function onInstall(bytes calldata data) external payable {
-      15            1 :         emit MockInstall(data);
-      16              :     }
-      17              : 
-      18            0 :     function onUninstall(bytes calldata data) external payable {
-      19            0 :         emit MockUninstall(data);
-      20              :     }
-      21              : }
-      22              : 
-      23              : contract MockCallee {
-      24              :     uint256 public bar;
-      25              :     string public data;
-      26              :     event Lorem();
-      27              :     error Haha();
-      28            8 :     function foo() external {
-      29            8 :         bar++;
-      30            8 :         emit Lorem();
-      31              :     }
-      32              : 
-      33            2 :     function lorem() external {
-      34            2 :         data = "lorem ipsum";
-      35              :     }
-      36              : 
-      37            6 :     function forceRevert() external {
-      38            6 :         revert Haha();
-      39              :     }
-      40              : }
-      41              : struct Call {
-      42              :     address target;
-      43              :     uint256 value;
-      44              :     bytes data;
-      45              : }
-      46              : contract KernelTest is Test {
-      47              :     IEntryPoint ep;
-      48              :     KernelFactory factory;
-      49              :     MockValidator mockValidator;
-      50              :     Kernel kernel;
-      51              :     MockCallee callee;
-      52              :     address executor;
-      53              : 
-      54              :     modifier unitTest {
-      55              :         vm.startPrank(address(ep));
-      56              :         _;
-      57              :         vm.stopPrank();
-      58              :     }
-      59              : 
-      60              :     modifier unitTestExecutor {
-      61              :         vm.startPrank(address(executor));
-      62              :         _;
-      63              :         vm.stopPrank();
-      64              :     }
-      65              : 
-      66              :     function setUp() external {
-      67              :         ep = EntryPointLib.deploy();
-      68              :         factory = new KernelFactory(ep);
-      69              :         mockValidator = new MockValidator();
-      70              :         callee = new MockCallee();
-      71              :         executor = makeAddr("Executor");
-      72              :         _initialize();
-      73              :     }
-      74              : 
-      75              :     function _initialize() internal {
-      76              :         kernel = factory.deploy(abi.encode("Kernel Test"));
-      77              : 
-      78              :         vm.startPrank(address(ep));
-      79              :         kernel.installModule(2, executor, abi.encode(hex"", ""));
-      80              :         vm.stopPrank();
-      81              :     }
-      82              : 
-      83              :     function test_deploy() external unitTest {
-      84              :         Kernel k = factory.deploy(hex"");
-      85              :     }
-      86              : 
-      87              :     function test_install_validator() external unitTest {
-      88              :         kernel.installModule(1, address(mockValidator), abi.encode(hex"deadbeef", "InternalData"));
-      89              :     }
-      90              : 
-      91              :     function test_execute() external unitTest {
-      92              :         vm.expectEmit(address(callee));
-      93              :         emit MockCallee.Lorem();
-      94              :         kernel.execute(bytes32(0), abi.encodePacked(address(callee), uint256(0), abi.encodeWithSelector(MockCallee.foo.selector)));
-      95              :         assertEq(callee.bar(), 1);
-      96              :     }
-      97              :     
-      98              :     function test_execute_fail() external unitTest {
-      99              :         vm.expectRevert(MockCallee.Haha.selector);
-     100              :         kernel.execute(bytes32(0), abi.encodePacked(address(callee), uint256(0), abi.encodeWithSelector(MockCallee.forceRevert.selector)));
-     101              :     }
-     102              :     
-     103              :     function test_execute_fail_try() external unitTest {
-     104              :         kernel.execute(LibERC7579.encodeMode(bytes1(0x00), bytes1(0x01), bytes4(0), bytes22(0)), abi.encodePacked(address(callee), uint256(0), abi.encodeWithSelector(MockCallee.forceRevert.selector)));
-     105              :     }
-     106              : 
-     107              :     function test_execute_batch() external unitTest {
-     108              :         Call[] memory calls = new Call[](2);
-     109              :         calls[0] = Call({
-     110              :             target : address(callee),
-     111              :             value : 0,
-     112              :             data : abi.encodeWithSelector(MockCallee.foo.selector)
-     113              :         });
-     114              :         calls[1] = Call({
-     115              :             target : address(callee),
-     116              :             value : 0,
-     117              :             data : abi.encodeWithSelector(MockCallee.lorem.selector)
-     118              :         });
-     119              :         assertEq(callee.data(), "");
-     120              :         vm.expectEmit(address(callee));
-     121              :         emit MockCallee.Lorem();
-     122              :         kernel.execute(LibERC7579.encodeMode(bytes1(0x01), bytes1(0x00), bytes4(0), bytes22(0)), abi.encode(calls));
-     123              :         assertEq(callee.bar(), 1);
-     124              :         assertEq(callee.data(), "lorem ipsum");
-     125              :     }
-     126              : 
-     127              :     function test_execute_batch_fail() external unitTest {
-     128              :         Call[] memory calls = new Call[](2);
-     129              :         calls[0] = Call({
-     130              :             target : address(callee),
-     131              :             value : 0,
-     132              :             data : abi.encodeWithSelector(MockCallee.foo.selector)
-     133              :         });
-     134              :         calls[1] = Call({
-     135              :             target : address(callee),
-     136              :             value : 0,
-     137              :             data : abi.encodeWithSelector(MockCallee.forceRevert.selector)
-     138              :         });
-     139              :         assertEq(callee.data(), "");
-     140              :         vm.expectRevert(MockCallee.Haha.selector);
-     141              :         kernel.execute(LibERC7579.encodeMode(bytes1(0x01), bytes1(0x00), bytes4(0), bytes22(0)), abi.encode(calls));
-     142              :     }
-     143              : 
-     144              :     function test_execute_batch_fail_try() external unitTest {
-     145              :         Call[] memory calls = new Call[](2);
-     146              :         calls[0] = Call({
-     147              :             target : address(callee),
-     148              :             value : 0,
-     149              :             data : abi.encodeWithSelector(MockCallee.foo.selector)
-     150              :         });
-     151              :         calls[1] = Call({
-     152              :             target : address(callee),
-     153              :             value : 0,
-     154              :             data : abi.encodeWithSelector(MockCallee.forceRevert.selector)
-     155              :         });
-     156              :         assertEq(callee.data(), "");
-     157              :         kernel.execute(LibERC7579.encodeMode(bytes1(0x01), bytes1(0x01), bytes4(0), bytes22(0)), abi.encode(calls));
-     158              :         assertEq(callee.bar(), 1);
-     159              :     }
-     160              : 
-     161              :     function test_execute_delegatecall() external unitTest {
-     162              :         vm.expectEmit(address(kernel));
-     163              :         emit MockCallee.Lorem();
-     164              :         kernel.execute(LibERC7579.encodeMode(bytes1(0xff), bytes1(0x00), bytes4(0), bytes22(0)), abi.encodePacked(address(callee), abi.encodeWithSelector(MockCallee.foo.selector)));
-     165              :     }
-     166              : 
-     167              :     function test_execute_delegatecall_fail() external unitTest {
-     168              :         vm.expectRevert(MockCallee.Haha.selector);
-     169              :         kernel.execute(LibERC7579.encodeMode(bytes1(0xff), bytes1(0x00), bytes4(0), bytes22(0)), abi.encodePacked(address(callee), abi.encodeWithSelector(MockCallee.forceRevert.selector)));
-     170              :     }
-     171              :     
-     172              :     function test_execute_delegatecall_fail_try() external unitTest {
-     173              :         kernel.execute(LibERC7579.encodeMode(bytes1(0xff), bytes1(0x01), bytes4(0), bytes22(0)), abi.encodePacked(address(callee), abi.encodeWithSelector(MockCallee.forceRevert.selector)));
-     174              :     }
-     175              :     
-     176              :     function test_execute_from_executor() external unitTestExecutor {
-     177              :         vm.expectEmit(address(callee));
-     178              :         emit MockCallee.Lorem();
-     179              :         kernel.executeFromExecutor(bytes32(0), abi.encodePacked(address(callee), uint256(0), abi.encodeWithSelector(MockCallee.foo.selector)));
-     180              :         assertEq(callee.bar(), 1);
-     181              :     }
-     182              : 
-     183              :     function test_execute_batch_from_executor() external unitTestExecutor {
-     184              :         Call[] memory calls = new Call[](2);
-     185              :         calls[0] = Call({
-     186              :             target : address(callee),
-     187              :             value : 0,
-     188              :             data : abi.encodeWithSelector(MockCallee.foo.selector)
-     189              :         });
-     190              :         calls[1] = Call({
-     191              :             target : address(callee),
-     192              :             value : 0,
-     193              :             data : abi.encodeWithSelector(MockCallee.lorem.selector)
-     194              :         });
-     195              :         assertEq(callee.data(), "");
-     196              :         vm.expectEmit(address(callee));
-     197              :         emit MockCallee.Lorem();
-     198              :         kernel.executeFromExecutor(LibERC7579.encodeMode(bytes1(0x01), bytes1(0x00), bytes4(0), bytes22(0)), abi.encode(calls));
-     199              :         assertEq(callee.bar(), 1);
-     200              :         assertEq(callee.data(), "lorem ipsum");
-     201              :     }
-     202              : 
-     203              :     function test_execute_delegatecall_from_executor() external unitTestExecutor {
-     204              :         vm.expectEmit(address(kernel));
-     205              :         emit MockCallee.Lorem();
-     206              :         kernel.executeFromExecutor(LibERC7579.encodeMode(bytes1(0xff), bytes1(0x00), bytes4(0), bytes22(0)), abi.encodePacked(address(callee), abi.encodeWithSelector(MockCallee.foo.selector)));
-     207              :     }
-     208              : }
-        
-
-
- - - - -
Generated by: LCOV version 2.1-1
-
- - - diff --git a/coverage/test/index-sort-f.html b/coverage/test/index-sort-f.html deleted file mode 100644 index 2bc33aec..00000000 --- a/coverage/test/index-sort-f.html +++ /dev/null @@ -1,105 +0,0 @@ - - - - - - - LCOV - lcov.info - test - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - testCoverageTotalHit
Test:lcov.infoLines:81.8 %119
Test Date:2025-05-22 05:44:20Functions:80.0 %54
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

File Sort by file nameLine Coverage Sort by line coverageFunction Coverage Sort by function coverage
Rate Total Hit Rate Total Hit
Kernel.t.sol -
81.8%81.8%
-
81.8 %11980.0 %54
-
-
- - - - -
Generated by: LCOV version 2.1-1
-
- - - diff --git a/coverage/test/index-sort-l.html b/coverage/test/index-sort-l.html deleted file mode 100644 index c3f81dfc..00000000 --- a/coverage/test/index-sort-l.html +++ /dev/null @@ -1,105 +0,0 @@ - - - - - - - LCOV - lcov.info - test - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - testCoverageTotalHit
Test:lcov.infoLines:81.8 %119
Test Date:2025-05-22 05:44:20Functions:80.0 %54
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

File Sort by file nameLine Coverage Sort by line coverageFunction Coverage Sort by function coverage
Rate Total Hit Rate Total Hit
Kernel.t.sol -
81.8%81.8%
-
81.8 %11980.0 %54
-
-
- - - - -
Generated by: LCOV version 2.1-1
-
- - - diff --git a/coverage/test/index.html b/coverage/test/index.html deleted file mode 100644 index ef49a5ce..00000000 --- a/coverage/test/index.html +++ /dev/null @@ -1,105 +0,0 @@ - - - - - - - LCOV - lcov.info - test - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - testCoverageTotalHit
Test:lcov.infoLines:81.8 %119
Test Date:2025-05-22 05:44:20Functions:80.0 %54
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

File Sort by file nameLine Coverage Sort by line coverageFunction Coverage Sort by function coverage
Rate Total Hit Rate Total Hit
Kernel.t.sol -
81.8%81.8%
-
81.8 %11980.0 %54
-
-
- - - - -
Generated by: LCOV version 2.1-1
-
- - - diff --git a/coverage/test/utils/EntryPointLib.sol.func-c.html b/coverage/test/utils/EntryPointLib.sol.func-c.html deleted file mode 100644 index 2b60c0bb..00000000 --- a/coverage/test/utils/EntryPointLib.sol.func-c.html +++ /dev/null @@ -1,82 +0,0 @@ - - - - - - - LCOV - lcov.info - test/utils/EntryPointLib.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - test/utils - EntryPointLib.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:100.0 %44
Test Date:2025-05-22 05:44:20Functions:100.0 %11
-
- -
- - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by function hit count
EntryPointLib.deploy14
-
-
- - - -
Generated by: LCOV version 2.1-1
-
- - - diff --git a/coverage/test/utils/EntryPointLib.sol.func.html b/coverage/test/utils/EntryPointLib.sol.func.html deleted file mode 100644 index 3e1d76d2..00000000 --- a/coverage/test/utils/EntryPointLib.sol.func.html +++ /dev/null @@ -1,82 +0,0 @@ - - - - - - - LCOV - lcov.info - test/utils/EntryPointLib.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - test/utils - EntryPointLib.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:100.0 %44
Test Date:2025-05-22 05:44:20Functions:100.0 %11
-
- -
- - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by function hit count
EntryPointLib.deploy14
-
-
- - - -
Generated by: LCOV version 2.1-1
-
- - - diff --git a/coverage/test/utils/EntryPointLib.sol.gcov.html b/coverage/test/utils/EntryPointLib.sol.gcov.html deleted file mode 100644 index 29e7ab88..00000000 --- a/coverage/test/utils/EntryPointLib.sol.gcov.html +++ /dev/null @@ -1,92 +0,0 @@ - - - - - - - LCOV - lcov.info - test/utils/EntryPointLib.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - test/utils - EntryPointLib.sol (source / functions)CoverageTotalHit
Test:lcov.infoLines:100.0 %44
Test Date:2025-05-22 05:44:20Functions:100.0 %11
-
- - - - - - - - -

-
            Line data    Source code
-
-       1              : pragma solidity ^0.8.0;
-       2              : 
-       3              : import {IEntryPoint} from "account-abstraction/interfaces/IEntryPoint.sol";
-       4              : 
-       5              : bytes constant ENTRYPOINT_0_8_INITCODE =
-       6              :     hex"0a59dbff790c23c976a548690c27297883cc66b4c67024f9117b0238995e35e96101806040523461019557604051610018604082610199565b600781526020810190664552433433333760c81b82526040519161003d604084610199565b600183526020830191603160f81b8352610056816101bc565b6101205261006384610357565b61014052519020918260e05251902080610100524660a0526040519060208201927f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f8452604083015260608201524660808201523060a082015260a081526100cc60c082610199565b5190206080523060c0526040516104f58082016001600160401b0381118382101761018157829161597a833903905ff0801561017657610160526040516154ea9081610490823960805181613511015260a051816135ce015260c051816134e2015260e051816135600152610100518161358601526101205181611884015261014051816118ad0152610160518181816116ce015281816120a801528181615061015261538c0152f35b6040513d5f823e3d90fd5b634e487b7160e01b5f52604160045260245ffd5b5f80fd5b601f909101601f19168101906001600160401b0382119082101761018157604052565b908151602081105f14610236575090601f8151116101f65760208151910151602082106101e7571790565b5f198260200360031b1b161790565b604460209160405192839163305a27a960e01b83528160048401528051918291826024860152018484015e5f828201840152601f01601f19168101030190fd5b6001600160401b03811161018157600254600181811c9116801561034d575b602082101461033957601f8111610306575b50602092601f82116001146102a557928192935f9261029a575b50508160011b915f199060031b1c19161760025560ff90565b015190505f80610281565b601f1982169360025f52805f20915f5b8681106102ee57508360019596106102d6575b505050811b0160025560ff90565b01515f1960f88460031b161c191690555f80806102c8565b919260206001819286850151815501940192016102b5565b60025f52601f60205f20910160051c810190601f830160051c015b81811061032e5750610267565b5f8155600101610321565b634e487b7160e01b5f52602260045260245ffd5b90607f1690610255565b908151602081105f14610382575090601f8151116101f65760208151910151602082106101e7571790565b6001600160401b03811161018157600354600181811c91168015610485575b602082101461033957601f8111610452575b50602092601f82116001146103f157928192935f926103e6575b50508160011b915f199060031b1c19161760035560ff90565b015190505f806103cd565b601f1982169360035f52805f20915f5b86811061043a5750836001959610610422575b505050811b0160035560ff90565b01515f1960f88460031b161c191690555f8080610414565b91926020600181928685015181550194019201610401565b60035f52601f60205f20910160051c810190601f830160051c015b81811061047a57506103b3565b5f815560010161046d565b90607f16906103a156fe6101606040526004361015610024575b3615610019575f80fd5b610022336131f4565b005b5f610140525f3560e01c806242dc53146125d957806301ffc9a7146124875780630396cb60146120cc57806309ccb8801461205b5780630bd28e3b14611fbf57806313c65a6e14611f84578063154e58dc14611f295780631b2e01b814611e93578063205c287814611cf257806322cdde4c14611c6e57806335567e1a14611bb45780635287ce1214611a9457806370a0823114611a29578063765e827f1461198b57806384b0196e1461184b578063850aaf62146117865780639b249f6914611622578063b760faf9146115e1578063bb9fe6bf146113f2578063c23a5cea1461114f5763dbed18e00361000f5734610ec95761012136612d56565b6101005260e052610130613824565b6101405190815b60e0518110610f2e575061014a8261303a565b61012052610140516080526101405160c0525b60e05160c0511061029b577fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f9726101405161014051a161014051608081905290815b60e05181106101e1576101b48361010051614a19565b610140517f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005d6101405180f35b6102436101f18260e05185613267565b73ffffffffffffffffffffffffffffffffffffffff610212602083016132fb565b167f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d6101405161014051a2806132a7565b9061014051915b80831061025c5750505060010161019e565b909194600190610289610270888587613109565b61027f60805161012051613176565b519060805161437c565b0195816080510160805201919061024a565b6102aa60c05160e05183613267565b73ffffffffffffffffffffffffffffffffffffffff6102d860206102ce84806132a7565b60a05293016132fb565b61014051911691905b60a05181106103055750505060a05160805101608052600160c0510160c05261015d565b610316816080510161012051613176565b516103248260a05185613109565b61014051915a81519273ffffffffffffffffffffffffffffffffffffffff61034b826132fb565b168452602081810135908501526fffffffffffffffffffffffffffffffff6080808301358281166060880152811c604087015260a083013560c0808801919091528301359182166101008701521c6101208501526103ac60e082018261331c565b9081610e15575b5050604051936103c282612ee9565b6020850152846040526040810151946effffffffffffffffffffffffffffff8660c08401511760608401511760808401511760a084015117610100840151176101208401511711610daf5750604081015160608201510160808201510160a08201510160c0820151016101008201510294856040860152845173ffffffffffffffffffffffffffffffffffffffff60e08183511692610475898d61046960408b018b61331c565b92909160805101614fb5565b0151169661014051978015610d7e575b87516040810151905173ffffffffffffffffffffffffffffffffffffffff169061014051506040519a8b8960208d01519260208301937f19822f7c00000000000000000000000000000000000000000000000000000000855260248401926104ec93615460565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081018d5261051c908d612c2d565b61014051908c5190846101405190602095f161014051519a3d602003610d73575b60405215610c80575015610c02575b505073ffffffffffffffffffffffffffffffffffffffff825116602083015190610140515260016020526040610140512077ffffffffffffffffffffffffffffffffffffffffffffffff8260401c165f5260205267ffffffffffffffff60405f20918254926105ba84612e80565b90551603610b99575a840311610b305760e0015160609073ffffffffffffffffffffffffffffffffffffffff16610827575b73ffffffffffffffffffffffffffffffffffffffff949260a0859360809360606106219801520135905a900301910152614f15565b911685036107be576107555761064b73ffffffffffffffffffffffffffffffffffffffff91614f15565b91166106ec5761065d576001016102e1565b60a490604051907f220266b600000000000000000000000000000000000000000000000000000000825260805101600482015260406024820152602160448201527f41413332207061796d61737465722065787069726564206f72206e6f7420647560648201527f65000000000000000000000000000000000000000000000000000000000000006084820152fd5b608482604051907f220266b600000000000000000000000000000000000000000000000000000000825260805101600482015260406024820152601460448201527f41413334207369676e6174757265206572726f720000000000000000000000006064820152fd5b608482604051907f220266b600000000000000000000000000000000000000000000000000000000825260805101600482015260406024820152601760448201527f414132322065787069726564206f72206e6f74206475650000000000000000006064820152fd5b608483604051907f220266b600000000000000000000000000000000000000000000000000000000825260805101600482015260406024820152601460448201527f41413234207369676e6174757265206572726f720000000000000000000000006064820152fd5b9897969594505a9883519961085b73ffffffffffffffffffffffffffffffffffffffff60e08d015116604087015190615482565b15610ac75760807f52b7512c000000000000000000000000000000000000000000000000000000009798999a9b01516040516108dc816108b060208a015160408b015190602084019d8e528960248501615460565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282612c2d565b8651608073ffffffffffffffffffffffffffffffffffffffff60e08301511691015161014051918b61014051928551926101405191f1983d908161014051843e51948251604084019b8c519015918215610abb575b508115610a8b575b50610a065750601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09101160191826040525a90031161097a5750946105ec565b80887f220266b60000000000000000000000000000000000000000000000000000000060a4935260805101600482015260406024820152602760448201527f41413336206f766572207061796d6173746572566572696669636174696f6e4760648201527f61734c696d6974000000000000000000000000000000000000000000000000006084820152fd5b8b610a87610a1261349e565b6040519384937f65c8fd4d0000000000000000000000000000000000000000000000000000000085526080510160048501526024840152600d60648401527f4141333320726576657274656400000000000000000000000000000000000000608484015260a0604484015260a4830190612de9565b0390fd5b9050601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa084019101105f610939565b6040141591505f610931565b608487604051907f220266b600000000000000000000000000000000000000000000000000000000825260805101600482015260406024820152601e60448201527f41413331207061796d6173746572206465706f73697420746f6f206c6f7700006064820152fd5b608487604051907f220266b600000000000000000000000000000000000000000000000000000000825260805101600482015260406024820152601e60448201527f41413236206f76657220766572696669636174696f6e4761734c696d697400006064820152fd5b608488604051907f220266b600000000000000000000000000000000000000000000000000000000825260805101600482015260406024820152601a60448201527f4141323520696e76616c6964206163636f756e74206e6f6e63650000000000006064820152fd5b610c0b91615482565b15610c17578b8061054c565b608488604051907f220266b600000000000000000000000000000000000000000000000000000000825260805101600482015260406024820152601760448201527f41413231206469646e2774207061792070726566756e640000000000000000006064820152fd5b8b903b610cf057608490604051907f220266b600000000000000000000000000000000000000000000000000000000825260805101600482015260406024820152601960448201527f41413230206163636f756e74206e6f74206465706c6f796564000000000000006064820152fd5b610cf861349e565b90610a876040519283927f65c8fd4d00000000000000000000000000000000000000000000000000000000845260805101600484015260606024840152600d60648401527f4141323320726576657274656400000000000000000000000000000000000000608484015260a0604484015260a4830190612de9565b61014051915061053d565b6101408051849052516020819052604090205490985081811115610da85750610140515b97610485565b8103610da2565b80887f220266b6000000000000000000000000000000000000000000000000000000006084935260805101600482015260406024820152601860448201527f41413934206761732076616c756573206f766572666c6f7700000000000000006064820152fd5b60348210610ed05781601411610ec95780359160248110610ec957603411610ec9576024810135608090811c60a0880152601490910135811c90860152606081901c15610e6b5760601c60e085015289806103b3565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4141393820696e76616c6964207061796d6173746572000000000000000000006044820152fd5b6101405180fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4141393320696e76616c6964207061796d6173746572416e64446174610000006044820152fd5b610f3b8160e05184613267565b92610f4684806132a7565b919073ffffffffffffffffffffffffffffffffffffffff610f69602088016132fb565b16956001871461111d5786610f86575b5050019250600101610137565b806040610f9492019061331c565b91873b15610ec957916040519283917f2dd8113300000000000000000000000000000000000000000000000000000000835286604484016040600486015252606483019160648860051b8501019281610140517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee182360301915b8b82106110c357505050505081611054917ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8580950301602485015261014051956131b6565b0381610140518a5af190816110a8575b5061109b57847f86a9f750000000000000000000000000000000000000000000000000000000006101405152600452602461014051fd5b929350839260015f610f79565b610140516110b591612c2d565b61014051610ec9575f611064565b9193967fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9c90879294969703018552863584811215610ec957602061110c600193858394016133bd565b98019501920188969594939161100e565b867f86a9f750000000000000000000000000000000000000000000000000000000006101405152600452602461014051fd5b34610ec95760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec957611186612cde565b3361014051526101405160205260016040610140512001908154916dffffffffffffffffffffffffffff8360081c169283156113945760981c65ffffffffffff1680156113365742106112d85780547fffffffffffffff000000000000000000000000000000000000000000000000ff1690556040805173ffffffffffffffffffffffffffffffffffffffff831681526020810184905233917fb7c918e0e249f999e965cafeb6c664271b3f4317d296461500e71da39f0cbda391a2610140519182918291829173ffffffffffffffffffffffffffffffffffffffff165af161126d612eba565b501561127a576101405180f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f6661696c656420746f207769746864726177207374616b6500000000000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f5374616b65207769746864726177616c206973206e6f742064756500000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f6d7573742063616c6c20756e6c6f636b5374616b6528292066697273740000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f207374616b6520746f2077697468647261770000000000000000000000006044820152fd5b34610ec957610140517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec9573361014051526101405160205260016040610140512001805463ffffffff8160781c169081156115835760ff16156115255765ffffffffffff4216019065ffffffffffff82116114f25780547fffffffffffffff000000000000ffffffffffffffffffffffffffffffffffff001678ffffffffffff00000000000000000000000000000000000000609884901b1617905560405165ffffffffffff909116815233907ffa9b3c14cc825c412c9ed81b3ba365a5b459439403f18829e572ed53a4180f0a90602090a26101405180f35b7f4e487b710000000000000000000000000000000000000000000000000000000061014051526011600452602461014051fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f616c726561647920756e7374616b696e670000000000000000000000000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f6e6f74207374616b6564000000000000000000000000000000000000000000006044820152fd5b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec95761161b611616612cde565b6131f4565b6101405180f35b34610ec95760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec95760043567ffffffffffffffff8111610ec95760206116766116b1923690600401612d01565b60405193849283927f570e1a3600000000000000000000000000000000000000000000000000000000845285600485015260248401916131b6565b03816101405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165af180156117785773ffffffffffffffffffffffffffffffffffffffff916101405191611749575b507f6ca7b80600000000000000000000000000000000000000000000000000000000610140515216600452602461014051fd5b61176b915060203d602011611771575b6117638183612c2d565b81019061318a565b82611716565b503d611759565b6040513d61014051823e3d90fd5b34610ec95760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec9576117bd612cde565b60243567ffffffffffffffff8111610ec9576117dd903690600401612d01565b604051929181908437820190610140518252610140519280610140519303915af4611806612eba565b90610a876040519283927f9941055400000000000000000000000000000000000000000000000000000000845215156004840152604060248401526044830190612de9565b34610ec957610140517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec9576119296118a87f0000000000000000000000000000000000000000000000000000000000000000614ccf565b6118d17f0000000000000000000000000000000000000000000000000000000000000000614e45565b60405190602090611937906118e68385612c2d565b6101405184525f3681376040519586957f0f00000000000000000000000000000000000000000000000000000000000000875260e08588015260e0870190612de9565b908582036040870152612de9565b4660608501523060808501526101405160a085015283810360c0850152818084519283815201930191610140515b82811061197457505050500390f35b835185528695509381019392810192600101611965565b34610ec95761199936612d56565b6119a4929192613824565b6119ad8361303a565b6119b8818585613898565b5061014051927fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f9728480a161014051915b8583106119f9576101b48585614a19565b909193600190611a1f611a0d878987613109565b611a178886613176565b51908861437c565b01940191906119e8565b34610ec95760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec95773ffffffffffffffffffffffffffffffffffffffff611a75612cde565b1661014051526101405160205260206040610140512054604051908152f35b34610ec95760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec95773ffffffffffffffffffffffffffffffffffffffff611ae0612cde565b604051611aec81612bab565b6101405181526101405160208201526101405160408201526101405160608201526080610140519101521661014051526101405160205260a06040610140512065ffffffffffff604051611b3f81612bab565b63ffffffff60018454948584520154916dffffffffffffffffffffffffffff6020820160ff8516151581526040830190828660081c1682528660806060860195878960781c168752019660981c1686526040519788525115156020880152511660408601525116606084015251166080820152f35b34610ec95760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec9576020611bed612cde565b73ffffffffffffffffffffffffffffffffffffffff611c0a612d2f565b91166101405152600182526040610140512077ffffffffffffffffffffffffffffffffffffffffffffffff82165f52825260405f20547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000006040519260401b16178152f35b34610ec95760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec95760043567ffffffffffffffff8111610ec9576101207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8236030112610ec957611cea602091600401612ee9565b604051908152f35b34610ec95760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec957611d29612cde565b6024359033610140515261014051602052604061014051208054808411611e355783611d5491612ead565b90556040805173ffffffffffffffffffffffffffffffffffffffff831681526020810184905233917fd1c19fbcd4551a5edfb66d43d2e337c04837afda3482b42bdf569a8fccdae5fb91a2610140519182918291829173ffffffffffffffffffffffffffffffffffffffff165af1611dca612eba565b5015611dd7576101405180f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6661696c656420746f20776974686472617700000000000000000000000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f576974686472617720616d6f756e7420746f6f206c61726765000000000000006044820152fd5b34610ec95760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec957611eca612cde565b73ffffffffffffffffffffffffffffffffffffffff611ee7612d2f565b91166101405152600160205277ffffffffffffffffffffffffffffffffffffffffffffffff6040610140512091165f52602052602060405f2054604051908152f35b34610ec957610140517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec95760206040517f29a0bca4af4be3421398da00295e58e6d7de38cb492214754cb6a47507dd6f8e8152f35b34610ec957610140517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec9576020611cea6134cb565b34610ec95760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec95760043577ffffffffffffffffffffffffffffffffffffffffffffffff81168103610ec957336101405152600160205277ffffffffffffffffffffffffffffffffffffffffffffffff6040610140512091165f5260205260405f206120528154612e80565b90556101405180f35b34610ec957610140517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec957602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec95760043563ffffffff8116809103610ec957336101405152610140516020526040610140512090801561242957600182015463ffffffff8160781c1682106123cb57612155906dffffffffffffffffffffffffffff349160081c16612e46565b91821561236d576dffffffffffffffffffffffffffff831161230f57546040516122d79161218282612bab565b815265ffffffffffff602082019160018352604081016dffffffffffffffffffffffffffff87168152606082019086825260016080840193610140518552336101405152610140516020526040610140512090518155019451151560ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008754169116178555517fffffffffffffffffffffffffffffffffff0000000000000000000000000000ff6effffffffffffffffffffffffffff008087549360081b16169116178455517fffffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffff72ffffffff0000000000000000000000000000008086549360781b1616911617835551167fffffffffffffff000000000000ffffffffffffffffffffffffffffffffffffff78ffffffffffff0000000000000000000000000000000000000083549260981b169116179055565b60405191825260208201527fa5ae833d0bb1dcd632d98a8b70973e8516812898e19bf27b70071ebc8dc52c0160403392a26101405180f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f7374616b65206f766572666c6f770000000000000000000000000000000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6e6f207374616b652073706563696669656400000000000000000000000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f63616e6e6f7420646563726561736520756e7374616b652074696d65000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f6d757374207370656369667920756e7374616b652064656c61790000000000006044820152fd5b34610ec95760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec9576004357fffffffff000000000000000000000000000000000000000000000000000000008116809103610ec957807f6930d3ee00000000000000000000000000000000000000000000000000000000602092149081156125af575b8115612585575b811561255b575b8115612531575b506040519015158152f35b7f01ffc9a70000000000000000000000000000000000000000000000000000000091501482612526565b7f3e84f021000000000000000000000000000000000000000000000000000000008114915061251f565b7fcf28ef970000000000000000000000000000000000000000000000000000000081149150612518565b7f989ccc580000000000000000000000000000000000000000000000000000000081149150612511565b34612a32576102007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112612a325760043567ffffffffffffffff8111612a325736602382011215612a325761263a903690602481600401359101612ca8565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc36016101c08112612a32576101406040519161267683612bab565b12612a325760405161268781612bf4565b60243573ffffffffffffffffffffffffffffffffffffffff81168103612a3257815260443560208201526064356040820152608435606082015260a435608082015260c43560a082015260e43560c08201526101043573ffffffffffffffffffffffffffffffffffffffff81168103612a325760e082015261012435610100820152610144356101208201528152602081019161016435835260408201906101843582526101a435606084015260808301916101c43583526101e43567ffffffffffffffff8111612a3257612760903690600401612d01565b955a90303303612b4d578651606081015195603f5a0260061c61271060a084015189010111612b25575f9681519182612a6b575b5050505050906127ac915a9003855101963691612ca8565b925a93855161010081015161012082015148018082105f14612a635750975b6127f873ffffffffffffffffffffffffffffffffffffffff60e08401511694518203606084015190614b09565b01925f928161290e5750505173ffffffffffffffffffffffffffffffffffffffff16945b5a900301019485029051928184105f146128ba5750506003811015612887576002036128595760209281611cea929361285481614c2a565b614b28565b7fdeadaa51000000000000000000000000000000000000000000000000000000006101405152602061014051fd5b7f4e487b710000000000000000000000000000000000000000000000000000000061014051526021600452602461014051fd5b816128f0929594969396039073ffffffffffffffffffffffffffffffffffffffff165f525f60205260405f209081540180915590565b5060038410156128875782612909926020951590614ba9565b611cea565b909691878251612921575b50505061281c565b90919293505a926003881015612a365760028803612957575b505060a061294e925a900391015190614b09565b90888080612919565b60a083015191803b15612a32578b925f92836129b3938c8b88604051998a98899788957f7c627b210000000000000000000000000000000000000000000000000000000087526004870152608060248701526084860190612de9565b9202604484015260648301520393f19081612a1d575b50612a1357610a876129d961349e565b6040519182917fad7954bc000000000000000000000000000000000000000000000000000000008352602060048401526024830190612de9565b60a061294e61293a565b5f612a2791612c2d565b5f610140528a6129c9565b5f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b9050976127cb565b915f9291838093602073ffffffffffffffffffffffffffffffffffffffff885116910192f115612a9e575b808080612794565b6127ac9392955060405191612ab161349e565b908151612aca575b505050604052600193909188612a96565b7f1c4fada7374c0a9ee8841fc38afe82932dc0f8e69012e927f061a8bae611a201905191602073ffffffffffffffffffffffffffffffffffffffff855116940151612b1a60405192839283612e2c565b0390a3888080612ab9565b7fdeaddead000000000000000000000000000000000000000000000000000000005f5260205ffd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4141393220696e7465726e616c2063616c6c206f6e6c790000000000000000006044820152fd5b60a0810190811067ffffffffffffffff821117612bc757604052565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b610140810190811067ffffffffffffffff821117612bc757604052565b6060810190811067ffffffffffffffff821117612bc757604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117612bc757604052565b67ffffffffffffffff8111612bc757601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b929192612cb482612c6e565b91612cc26040519384612c2d565b829481845281830111612a32578281602093845f960137010152565b6004359073ffffffffffffffffffffffffffffffffffffffff82168203612a3257565b9181601f84011215612a325782359167ffffffffffffffff8311612a325760208381860195010111612a3257565b6024359077ffffffffffffffffffffffffffffffffffffffffffffffff82168203612a3257565b9060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc830112612a325760043567ffffffffffffffff8111612a325760040182601f82011215612a325780359267ffffffffffffffff8411612a32576020808301928560051b010111612a3257919060243573ffffffffffffffffffffffffffffffffffffffff81168103612a325790565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f602080948051918291828752018686015e5f8582860101520116010190565b604090612e43939281528160208201520190612de9565b90565b91908201809211612e5357565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114612e535760010190565b91908203918211612e5357565b3d15612ee4573d90612ecb82612c6e565b91612ed96040519384612c2d565b82523d5f602084013e565b606090565b604290612ef5816135f4565b612efd6134cb565b91612f07816132fb565b91801561300557905b60c0612f1f606083018361331c565b90816040519182372091612f3660e082018261331c565b908160405191823720926040519473ffffffffffffffffffffffffffffffffffffffff60208701977f29a0bca4af4be3421398da00295e58e6d7de38cb492214754cb6a47507dd6f8e895216604087015260208301356060870152608086015260a085015260808101358285015260a081013560e085015201356101008301526101208201526101208152612fcd61014082612c2d565b519020604051917f19010000000000000000000000000000000000000000000000000000000000008352600283015260228201522090565b50613013604082018261331c565b90816040519182372090612f10565b67ffffffffffffffff8111612bc75760051b60200190565b9061304482613022565b6130516040519182612c2d565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe061307f8294613022565b01905f5b82811061308f57505050565b60209060405161309e81612bab565b6040516130aa81612bf4565b5f81525f848201525f60408201525f60608201525f60808201525f60a08201525f60c08201525f60e08201525f6101008201525f61012082015281525f838201525f60408201525f60608201525f608082015282828501015201613083565b91908110156131495760051b810135907ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee181360301821215612a32570190565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b80518210156131495760209160051b010190565b90816020910312612a32575173ffffffffffffffffffffffffffffffffffffffff81168103612a325790565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe093818652868601375f8582860101520116010190565b7f2da466a7b24304f47e87fa2e1e5a81b9831ce54fec19055ce277ca2f39ba42c4602073ffffffffffffffffffffffffffffffffffffffff61325b348573ffffffffffffffffffffffffffffffffffffffff165f525f60205260405f209081540180915590565b936040519485521692a2565b91908110156131495760051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa181360301821215612a32570190565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215612a32570180359067ffffffffffffffff8211612a3257602001918160051b36038313612a3257565b3573ffffffffffffffffffffffffffffffffffffffff81168103612a325790565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215612a32570180359067ffffffffffffffff8211612a3257602001918136038313612a3257565b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe182360301811215612a3257016020813591019167ffffffffffffffff8211612a32578136038313612a3257565b80359173ffffffffffffffffffffffffffffffffffffffff83168303612a325773ffffffffffffffffffffffffffffffffffffffff612e43931681526020820135602082015261348f61348361344a61342f61341c604087018761336d565b61012060408801526101208701916131b6565b61343c606087018761336d565b9086830360608801526131b6565b6080850135608085015260a085013560a085015260c085013560c085015261347560e086018661336d565b9085830360e08701526131b6565b9261010081019061336d565b916101008185039101526131b6565b3d61080081116134c2575b604051906020818301016040528082525f602083013e90565b506108006134a9565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163014806135cb575b15613533577f000000000000000000000000000000000000000000000000000000000000000090565b60405160208101907f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f82527f000000000000000000000000000000000000000000000000000000000000000060408201527f000000000000000000000000000000000000000000000000000000000000000060608201524660808201523060a082015260a081526135c560c082612c2d565b51902090565b507f0000000000000000000000000000000000000000000000000000000000000000461461350a565b613601604082018261331c565b909161360d8284614c7a565b1561381d5761361b906132fb565b60175f80833c5f51907fef010000000000000000000000000000000000000000000000000000000000007fffffff000000000000000000000000000000000000000000000000000000000083160361375b575060181b91601482116136bb5750506040517fffffffffffffffffffffffffffffffffffffffff000000000000000000000000808060208401941616168252601481526135c5603482612c2d565b81601411612a325760206135c5916040519384917fffffffffffffffffffffffffffffffffffffffff000000000000000000000000808086860199161616875260147fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec83019101603484013781015f8382015203017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282612c2d565b3b156137bf5760646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f6e6f7420616e204549502d373730322064656c656761746500000000000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f73656e64657220686173206e6f20636f646500000000000000000000000000006044820152fd5b5050505f90565b7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005c6138705760017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005d565b7f3ee5aeb5000000000000000000000000000000000000000000000000000000005f5260045ffd5b92919092835f5b8181106138ac5750505050565b6138b68185613176565b516138c2828486613109565b5f915a81519273ffffffffffffffffffffffffffffffffffffffff6138e6826132fb565b168452602081013560208501526080810135936fffffffffffffffffffffffffffffffff8560801c951694604082019060608301968752815260c0820160a0840135815260c0840135906fffffffffffffffffffffffffffffffff8260801c9216916101208501906101008601938452815261396560e087018761331c565b9081614316575b505060405161397a87612ee9565b9960208a019a8b528160405285519586855117825117926effffffffffffffffffffffffffffff60808a01948551179560a08b0196875117895117905117116142b45750519051019051019051019051019051029560408601918783528973ffffffffffffffffffffffffffffffffffffffff60e08951613a0f8b8483511695613a0760408d018d61331c565b929091614fb5565b015116985f99801561428d575b89516040810151905173ffffffffffffffffffffffffffffffffffffffff1680916040519d8e808d8b519360208301947f19822f7c0000000000000000000000000000000000000000000000000000000086526024840192613a7d93615460565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081018252613aad9082612c2d565b51905f6020948194f15f519c3d602003614285575b6040521561419a575015614120575b505073ffffffffffffffffffffffffffffffffffffffff8451166020850151905f52600160205260405f2077ffffffffffffffffffffffffffffffffffffffffffffffff8260401c165f5260205267ffffffffffffffff60405f2091825492613b3984612e80565b905516036140bb575a8603116140565773ffffffffffffffffffffffffffffffffffffffff60e0606094015116613d96575b505073ffffffffffffffffffffffffffffffffffffffff949260a085936080936060613ba29801520135905a900301910152614f15565b9116613d3157613ccc57613bca73ffffffffffffffffffffffffffffffffffffffff91614f15565b9116613c6757613bdc5760010161389f565b60a490604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152602160448201527f41413332207061796d61737465722065787069726564206f72206e6f7420647560648201527f65000000000000000000000000000000000000000000000000000000000000006084820152fd5b608482604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601460448201527f41413334207369676e6174757265206572726f720000000000000000000000006064820152fd5b608482604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601760448201527f414132322065787069726564206f72206e6f74206475650000000000000000006064820152fd5b608483604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601460448201527f41413234207369676e6174757265206572726f720000000000000000000000006064820152fd5b909c9b9a99989796505a9085519d60e08f015173ffffffffffffffffffffffffffffffffffffffff168151613dca91615482565b15613ff157613e1d7f52b7512c00000000000000000000000000000000000000000000000000000000999a9b9c9d9e9f60800151926108b060405193849251905190602084019d8e528960248501615460565b5f8088518b82608073ffffffffffffffffffffffffffffffffffffffff60e08501511693015192865193f1983d90815f843e51948251604084019b8c519015918215613fe5575b508115613fb5575b50613f385750601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09101160191826040525a900311613eb05750948260a0613b6b565b80887f220266b60000000000000000000000000000000000000000000000000000000060a49352600482015260406024820152602760448201527f41413336206f766572207061796d6173746572566572696669636174696f6e4760648201527f61734c696d6974000000000000000000000000000000000000000000000000006084820152fd5b8b610a87613f4461349e565b6040519384937f65c8fd4d00000000000000000000000000000000000000000000000000000000855260048501526024840152600d60648401527f4141333320726576657274656400000000000000000000000000000000000000608484015260a0604484015260a4830190612de9565b9050601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa084019101105f613e6c565b6040141591505f613e64565b608489604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601e60448201527f41413331207061796d6173746572206465706f73697420746f6f206c6f7700006064820152fd5b608489604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601e60448201527f41413236206f76657220766572696669636174696f6e4761734c696d697400006064820152fd5b60848a604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601a60448201527f4141323520696e76616c6964206163636f756e74206e6f6e63650000000000006064820152fd5b61412991615482565b15614135575f80613ad1565b60848a604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601760448201527f41413231206469646e2774207061792070726566756e640000000000000000006064820152fd5b8d903b61420657608490604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601960448201527f41413230206163636f756e74206e6f74206465706c6f796564000000000000006064820152fd5b61420e61349e565b90610a876040519283927f65c8fd4d000000000000000000000000000000000000000000000000000000008452600484015260606024840152600d60648401527f4141323320726576657274656400000000000000000000000000000000000000608484015260a0604484015260a4830190612de9565b5f9150613ac2565b9950815f525f60205260405f20548181115f146142ad57505f5b99613a1c565b81036142a7565b808f7f220266b60000000000000000000000000000000000000000000000000000000060849352600482015260406024820152601860448201527f41413934206761732076616c756573206f766572666c6f7700000000000000006064820152fd5b60348210610ed05781601411612a3257803560601c9160248110612a3257601482013590603411612a32576fffffffffffffffffffffffffffffffff60248193013560801c1660a089015260801c1660808701528015610e6b5760e08601525f8061396c565b9092915a60608201516040519586614397606083018361331c565b5f60038211614a11575b7fffffffff00000000000000000000000000000000000000000000000000000000167f8dd7712f00000000000000000000000000000000000000000000000000000000036148a3575050505f6144ae6145a261443c61446e602095868a01516040519384927f8dd7712f000000000000000000000000000000000000000000000000000000008a8501526040602485015260648401906133bd565b906044830152037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282612c2d565b6108b06040519384927e42dc5300000000000000000000000000000000000000000000000000000000888501526102006024850152610224840190612de9565b614571604484018b60806101a091610120815173ffffffffffffffffffffffffffffffffffffffff8151168652602081015160208701526040810151604087015260608101516060870152838101518487015260a081015160a087015260c081015160c087015273ffffffffffffffffffffffffffffffffffffffff60e08201511660e087015261010081015161010087015201516101208501526020810151610140850152604081015161016085015260608101516101808501520151910152565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc8382030161020484015287612de9565b828151910182305af15f5196604052156145bd575b50505050565b9091929394505f3d602014614896575b7fdeaddead00000000000000000000000000000000000000000000000000000000810361465957608485604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152600f60448201527f41413935206f7574206f662067617300000000000000000000000000000000006064820152fd5b92935090917fdeadaa5100000000000000000000000000000000000000000000000000000000036146bc57506146a16146966146b1925a90612ead565b608084015190612e46565b6040830151836128548295614c2a565b905b5f8080806145b7565b9061472f9060405160208501518551907ff62676f440ff169a3a9afdbf812e89e7f95975ee8e5c31214ffdef631c5f4792602073ffffffffffffffffffffffffffffffffffffffff84511693015161471261349e565b9061472260405192839283612e2c565b0390a36040525a90612ead565b61473f6080840191825190612e46565b915f905a92855161010081015161012082015148018082105f1461488e5750955b61478d73ffffffffffffffffffffffffffffffffffffffff60e08401511693518203606084015190614b09565b01925f928061485f5750505173ffffffffffffffffffffffffffffffffffffffff16935b5a900301019283026040850151928184105f14614813575050806147e6575090816147e0929361285481614c2a565b906146b3565b807f4e487b7100000000000000000000000000000000000000000000000000000000602492526021600452fd5b614848908284939795039073ffffffffffffffffffffffffffffffffffffffff165f525f60205260405f209081540180915590565b506147e6575090825f61485a93614ba9565b6147e0565b9591905161486e575b506147b1565b935090506148875a9360a05f955a900391015190614b09565b905f614868565b905095614760565b5060205f803e5f516145cd565b614a0893506149dc916148e8917e42dc5300000000000000000000000000000000000000000000000000000000602086015261020060248601526102248501916131b6565b6149ab604484018860806101a091610120815173ffffffffffffffffffffffffffffffffffffffff8151168652602081015160208701526040810151604087015260608101516060870152838101518487015260a081015160a087015260c081015160c087015273ffffffffffffffffffffffffffffffffffffffff60e08201511660e087015261010081015161010087015201516101208501526020810151610140850152604081015161016085015260608101516101808501520151910152565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc8382030161020484015284612de9565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101885287612c2d565b60205f876145a2565b5081356143a1565b73ffffffffffffffffffffffffffffffffffffffff168015614aab575f80809381935af1614a45612eba565b5015614a4d57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f41413931206661696c65642073656e6420746f2062656e6566696369617279006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4141393020696e76616c69642062656e656669636961727900000000000000006044820152fd5b90619c408201811115614b2257606491600a9103020490565b50505f90565b9190917f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f6080602083015192519473ffffffffffffffffffffffffffffffffffffffff86511694602073ffffffffffffffffffffffffffffffffffffffff60e089015116970151916040519283525f602084015260408301526060820152a4565b9060807f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f91602084015193519573ffffffffffffffffffffffffffffffffffffffff87511695602073ffffffffffffffffffffffffffffffffffffffff60e08a015116980151926040519384521515602084015260408301526060820152a4565b60208101519051907f67b4fa9642f42120bf031f3051d1824b0fe25627945b27b8a6a65d5761d5482e60208073ffffffffffffffffffffffffffffffffffffffff855116940151604051908152a3565b90600211614cca57357fffffffffffffffffffffffffffffffffffffffff000000000000000000000000167f77020000000000000000000000000000000000000000000000000000000000001490565b505f90565b60ff8114614d2e5760ff811690601f8211614d065760405191614cf3604084612c2d565b6020808452838101919036833783525290565b7fb3512b0c000000000000000000000000000000000000000000000000000000005f5260045ffd5b506040515f6002548060011c9160018216918215614e3b575b602084108314614e0e578385528492908115614dd15750600114614d72575b612e4392500382612c2d565b5060025f90815290917f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace5b818310614db5575050906020612e4392820101614d66565b6020919350806001915483858801015201910190918392614d9d565b60209250612e439491507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001682840152151560051b820101614d66565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b92607f1692614d47565b60ff8114614e695760ff811690601f8211614d065760405191614cf3604084612c2d565b506040515f6003548060011c9160018216918215614f0b575b602084108314614e0e578385528492908115614dd15750600114614eac57612e4392500382612c2d565b5060035f90815290917fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b5b818310614eef575050906020612e4392820101614d66565b6020919350806001915483858801015201910190918392614ed7565b92607f1692614e82565b8015614fae575f60408051614f2981612c11565b828152826020820152015273ffffffffffffffffffffffffffffffffffffffff81169065ffffffffffff8160a01c16908115614fa0575b60409060d01c9165ffffffffffff825191614f7a83612c11565b8583528460208401521691829101524211908115614f9757509091565b90504211159091565b65ffffffffffff9150614f60565b505f905f90565b929190915f9080614fc8575b5050505050565b83519473ffffffffffffffffffffffffffffffffffffffff86511695614fee8386614c7a565b61535f5750853b6152fa576014821061529557604085510151602060405180927f570e1a36000000000000000000000000000000000000000000000000000000008252826004830152818781615048602482018a8d6131b6565b039273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690f190811561528a57849161526b575b5073ffffffffffffffffffffffffffffffffffffffff811680156152065787036151a1573b1561513c5750601411615139577fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d91604091503573ffffffffffffffffffffffffffffffffffffffff60e06020860151955101511673ffffffffffffffffffffffffffffffffffffffff83519260601c1682526020820152a35f80808080614fc1565b80fd5b608490604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152602060448201527f4141313520696e6974436f6465206d757374206372656174652073656e6465726064820152fd5b608482604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152602060448201527f4141313420696e6974436f6465206d7573742072657475726e2073656e6465726064820152fd5b608483604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601b60448201527f4141313320696e6974436f6465206661696c6564206f72204f4f4700000000006064820152fd5b615284915060203d602011611771576117638183612c2d565b5f615091565b6040513d86823e3d90fd5b608490604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601760448201527f4141393920696e6974436f646520746f6f20736d616c6c0000000000000000006064820152fd5b608490604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601f60448201527f414131302073656e64657220616c726561647920636f6e7374727563746564006064820152fd5b945050919050601482116153735750505050565b604073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169301519082601411612a3257833b15612a32575f809461542f96604051978896879586937fc09ad0d900000000000000000000000000000000000000000000000000000000855260048501526040602485015260147fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec60448601930191016131b6565b0393f1801561545557615445575b8080806145b7565b5f61544f91612c2d565b5f61543d565b6040513d5f823e3d90fd5b615478604092959493956060835260608301906133bd565b9460208201520152565b73ffffffffffffffffffffffffffffffffffffffff165f525f60205260405f2090815481811061381d5703905560019056fea2646970667358221220a2ee7c02d47f72772240d0dfa7174d99b6049a68ccdf3d4434c3918f6bd9c1e164736f6c634300081c003360a08060405234602f57336080526104c19081610034823960805181818160d80152818161023401526102e10152f35b5f80fdfe60806040526004361015610011575f80fd5b5f3560e01c8063570e1a3614610258578063b0d691fe146101ea5763c09ad0d91461003a575f80fd5b346101e65760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101e65760043573ffffffffffffffffffffffffffffffffffffffff811681036101e65760243567ffffffffffffffff81116101e657366023820112156101e6575f916100bd83923690602481600401359101610384565b906100ff73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163314610426565b82602083519301915af11561011057005b3d61080081116101dd575b60c460405160208382010160405282815260208101925f843e7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f6040519485937f65c8fd4d0000000000000000000000000000000000000000000000000000000085525f6004860152606060248601528260648601527f4141313320454950373730322073656e64657220696e6974206661696c656400608486015260a060448601525180918160a48701528686015e5f85828601015201168101030190fd5b5061080061011b565b5f80fd5b346101e6575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101e657602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b346101e65760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101e65760043567ffffffffffffffff81116101e657366023820112156101e65780600401359067ffffffffffffffff82116101e65736602483830101116101e6575f9161030873ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163314610426565b806014116101e6576020916103455f927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec36910160388401610384565b90826024858451940192013560601c5af161037c575b60209073ffffffffffffffffffffffffffffffffffffffff60405191168152f35b505f5161035b565b92919267ffffffffffffffff82116103f957604051917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f81601f8401160116830183811067ffffffffffffffff8211176103f9576040528294818452818301116101e6578281602093845f960137010152565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b1561042d57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602060248201527f414139372073686f756c642063616c6c2066726f6d20456e747279506f696e746044820152fdfea26469706673582212206423798798d408242e814ed5c031f1afcdccad1146c1c11fab88cce1fdaa4c4a64736f6c634300081c0033";
-       7              : address constant ENTRYPOINT_0_8 = 0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108;
-       8              : address constant DETERMINISTIC_DEPLOYER = 0x4e59b44847b379578588920cA78FbF26c0B4956C;
-       9              : 
-      10              : library EntryPointLib {
-      11           14 :     function deploy() internal returns (IEntryPoint) {
-      12           14 :         (bool success,) = DETERMINISTIC_DEPLOYER.call(ENTRYPOINT_0_8_INITCODE);
-      13           14 :         require(success);
-      14           14 :         return IEntryPoint(payable(ENTRYPOINT_0_8));
-      15              :     }
-      16              : }
-        
-
-
- - - - -
Generated by: LCOV version 2.1-1
-
- - - diff --git a/coverage/test/utils/index-sort-f.html b/coverage/test/utils/index-sort-f.html deleted file mode 100644 index 7e897e71..00000000 --- a/coverage/test/utils/index-sort-f.html +++ /dev/null @@ -1,105 +0,0 @@ - - - - - - - LCOV - lcov.info - test/utils - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - test/utilsCoverageTotalHit
Test:lcov.infoLines:100.0 %44
Test Date:2025-05-22 05:44:20Functions:100.0 %11
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

File Sort by file nameLine Coverage Sort by line coverageFunction Coverage Sort by function coverage
Rate Total Hit Rate Total Hit
EntryPointLib.sol -
100.0%
-
100.0 %44100.0 %11
-
-
- - - - -
Generated by: LCOV version 2.1-1
-
- - - diff --git a/coverage/test/utils/index-sort-l.html b/coverage/test/utils/index-sort-l.html deleted file mode 100644 index 7fc9707c..00000000 --- a/coverage/test/utils/index-sort-l.html +++ /dev/null @@ -1,105 +0,0 @@ - - - - - - - LCOV - lcov.info - test/utils - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - test/utilsCoverageTotalHit
Test:lcov.infoLines:100.0 %44
Test Date:2025-05-22 05:44:20Functions:100.0 %11
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

File Sort by file nameLine Coverage Sort by line coverageFunction Coverage Sort by function coverage
Rate Total Hit Rate Total Hit
EntryPointLib.sol -
100.0%
-
100.0 %44100.0 %11
-
-
- - - - -
Generated by: LCOV version 2.1-1
-
- - - diff --git a/coverage/test/utils/index.html b/coverage/test/utils/index.html deleted file mode 100644 index 6e8fe632..00000000 --- a/coverage/test/utils/index.html +++ /dev/null @@ -1,105 +0,0 @@ - - - - - - - LCOV - lcov.info - test/utils - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - test/utilsCoverageTotalHit
Test:lcov.infoLines:100.0 %44
Test Date:2025-05-22 05:44:20Functions:100.0 %11
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

File Sort by file nameLine Coverage Sort by line coverageFunction Coverage Sort by function coverage
Rate Total Hit Rate Total Hit
EntryPointLib.sol -
100.0%
-
100.0 %44100.0 %11
-
-
- - - - -
Generated by: LCOV version 2.1-1
-
- - - diff --git a/coverage/updown.png b/coverage/updown.png deleted file mode 100644 index aa56a238b3e6c435265250f9266cd1b8caba0f20..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 117 zcmeAS@N?(olHy`uVBq!ia0vp^AT}Qd8;}%R+`Ae`*?77*hG?8mPH5^{)z4*}Q$iB}huR`+ From bb98f28f83009dade61ea0c2cc319b4bd9e3d682 Mon Sep 17 00:00:00 2001 From: leekt Date: Thu, 22 May 2025 05:45:15 +0900 Subject: [PATCH 008/121] removed lcov --- lcov.info | 626 ------------------------------------------------------ 1 file changed, 626 deletions(-) delete mode 100644 lcov.info diff --git a/lcov.info b/lcov.info deleted file mode 100644 index b7b97563..00000000 --- a/lcov.info +++ /dev/null @@ -1,626 +0,0 @@ -TN: -SF:src/Kernel.sol -DA:20,0 -FN:20,Kernel.onlyEntryPointOrSelf -FNDA:0,Kernel.onlyEntryPointOrSelf -DA:21,0 -BRDA:21,0,0,- -BRDA:21,0,1,9 -DA:25,14 -FN:25,Kernel.constructor -FNDA:14,Kernel.constructor -DA:26,14 -DA:29,14 -FN:29,Kernel._domainNameAndVersion -FNDA:14,Kernel._domainNameAndVersion -DA:30,14 -DA:31,14 -DA:41,0 -FN:41,Kernel.validateUserOp -FNDA:0,Kernel.validateUserOp -DA:47,0 -DA:48,0 -DA:50,0 -BRDA:50,1,0,- -DA:51,0 -DA:57,0 -FN:57,Kernel._processUserOp -FNDA:0,Kernel._processUserOp -DA:64,0 -DA:65,0 -DA:66,0 -BRDA:66,2,0,- -DA:67,0 -DA:68,0 -DA:70,0 -DA:72,0 -DA:73,0 -DA:74,0 -DA:76,0 -DA:77,0 -DA:80,0 -FN:80,Kernel.isValidSignature -FNDA:0,Kernel.isValidSignature -DA:83,0 -FN:83,Kernel.executeUserOp -FNDA:0,Kernel.executeUserOp -DA:84,0 -DA:87,9 -FN:87,Kernel.execute -FNDA:9,Kernel.execute -DA:88,9 -DA:91,3 -FN:91,Kernel.executeFromExecutor -FNDA:3,Kernel.executeFromExecutor -DA:92,3 -DA:95,0 -FN:95,Kernel._fallback -FNDA:0,Kernel._fallback -DA:96,0 -DA:97,0 -DA:98,0 -BRDA:98,3,0,- -DA:99,0 -DA:101,0 -DA:102,0 -BRDA:102,4,0,- -DA:103,0 -DA:106,0 -DA:107,0 -BRDA:107,5,0,- -BRDA:107,5,1,- -DA:108,0 -DA:109,0 -BRDA:109,6,0,- -DA:110,0 -DA:112,0 -BRDA:112,7,0,- -DA:113,0 -DA:115,0 -BRDA:115,8,0,- -DA:116,0 -DA:126,15 -FN:126,Kernel.installModule -FNDA:15,Kernel.installModule -DA:127,15 -DA:129,15 -DA:131,15 -DA:134,0 -FN:134,Kernel.setRoot -FNDA:0,Kernel.setRoot -DA:135,0 -DA:139,0 -FN:139,Kernel.installModule -FNDA:0,Kernel.installModule -DA:140,0 -BRDA:140,9,0,- -BRDA:140,9,1,- -DA:142,0 -BRDA:142,10,0,- -BRDA:142,10,1,- -DA:143,0 -DA:147,0 -BRDA:147,11,0,- -BRDA:147,11,1,- -DA:148,0 -DA:149,0 -DA:150,0 -DA:154,0 -FN:154,Kernel._verifyInstallSignature -FNDA:0,Kernel._verifyInstallSignature -DA:159,0 -DA:160,0 -DA:161,0 -DA:162,0 -DA:172,0 -DA:175,0 -FN:175,Kernel.fallback -FNDA:0,Kernel.fallback -DA:176,0 -FNF:15 -FNH:5 -LF:70 -LH:13 -BRF:17 -BRH:1 -end_of_record -TN: -SF:src/KernelFactory.sol -DA:10,14 -FN:10,KernelFactory.constructor -FNDA:14,KernelFactory.constructor -DA:11,14 -DA:14,15 -FN:14,KernelFactory.deploy -FNDA:15,KernelFactory.deploy -DA:15,15 -DA:16,15 -DA:17,15 -DA:20,0 -FN:20,KernelFactory.deployWithAdditionalPackage -FNDA:0,KernelFactory.deployWithAdditionalPackage -DA:21,0 -DA:22,0 -DA:24,0 -DA:25,0 -DA:26,0 -FNF:3 -FNH:2 -LF:12 -LH:6 -BRF:0 -BRH:0 -end_of_record -TN: -SF:src/Lib4337.sol -DA:24,0 -FN:24,Lib4337.chainAgnosticUserOpHash -FNDA:0,Lib4337.chainAgnosticUserOpHash -DA:25,0 -DA:26,0 -DA:27,0 -DA:32,0 -FN:32,Lib4337._hashTypedDataSansChainId -FNDA:0,Lib4337._hashTypedDataSansChainId -DA:37,0 -DA:40,0 -DA:41,0 -DA:42,0 -DA:43,0 -DA:44,0 -DA:46,0 -DA:47,0 -DA:48,0 -DA:49,0 -DA:50,0 -DA:51,0 -FNF:2 -FNH:0 -LF:17 -LH:0 -BRF:0 -BRH:0 -end_of_record -TN: -SF:src/core/ExecutionManager.sol -DA:7,12 -FN:7,ExecutionManager._execute -FNDA:12,ExecutionManager._execute -DA:8,12 -DA:9,12 -DA:10,12 -DA:11,12 -BRDA:11,0,0,9 -BRDA:11,0,1,- -DA:12,9 -DA:13,3 -BRDA:13,1,0,3 -BRDA:13,1,1,- -DA:14,3 -DA:16,0 -DA:19,12 -DA:20,12 -BRDA:20,2,0,4 -BRDA:20,2,1,- -DA:21,4 -DA:22,8 -BRDA:22,3,0,4 -BRDA:22,3,1,- -DA:23,4 -DA:24,4 -BRDA:24,4,0,4 -BRDA:24,4,1,- -DA:25,4 -DA:27,0 -DA:29,12 -DA:32,4 -FN:32,ExecutionManager._executeCall -FNDA:4,ExecutionManager._executeCall -DA:33,4 -DA:34,4 -DA:35,4 -BRDA:35,5,0,2 -DA:36,2 -DA:40,4 -FN:40,ExecutionManager._executeDelegateCall -FNDA:4,ExecutionManager._executeDelegateCall -DA:41,4 -DA:42,4 -DA:43,4 -BRDA:43,6,0,2 -DA:44,2 -DA:48,4 -FN:48,ExecutionManager._executeBatchCall -FNDA:4,ExecutionManager._executeBatchCall -DA:49,4 -DA:50,4 -DA:51,4 -DA:53,4 -DA:54,8 -DA:55,8 -DA:56,8 -BRDA:56,7,0,2 -DA:57,2 -DA:63,3 -FN:63,ExecutionManager._onRevertThrow -FNDA:3,ExecutionManager._onRevertThrow -DA:66,3 -DA:67,3 -DA:71,3 -FN:71,ExecutionManager._onRevertSilent -FNDA:3,ExecutionManager._onRevertSilent -DA:74,12 -FN:74,ExecutionManager._call -FNDA:12,ExecutionManager._call -DA:77,12 -DA:78,12 -DA:79,12 -DA:83,4 -FN:83,ExecutionManager._delegateCall -FNDA:4,ExecutionManager._delegateCall -DA:86,4 -DA:87,4 -DA:89,4 -FNF:8 -FNH:8 -LF:49 -LH:47 -BRF:13 -BRH:8 -end_of_record -TN: -SF:src/core/ExecutorManager.sol -DA:17,17 -FN:17,ExecutorManager._executorStorage -FNDA:17,ExecutorManager._executorStorage -DA:19,17 -DA:23,0 -FN:23,ExecutorManager.executorConfig -FNDA:0,ExecutorManager.executorConfig -DA:24,0 -DA:27,17 -FN:27,ExecutorManager._executorConfig -FNDA:17,ExecutorManager._executorConfig -DA:28,17 -DA:31,14 -FN:31,ExecutorManager._installExecutor -FNDA:14,ExecutorManager._installExecutor -DA:33,14 -DA:34,14 -BRDA:34,0,0,14 -DA:35,14 -DA:37,14 -DA:40,0 -FN:40,ExecutorManager._uninstallExecutor -FNDA:0,ExecutorManager._uninstallExecutor -DA:41,0 -FNF:5 -FNH:3 -LF:13 -LH:9 -BRF:1 -BRH:1 -end_of_record -TN: -SF:src/core/HookManager.sol -DA:14,0 -FN:14,HookManager._installHook -FNDA:0,HookManager._installHook -DA:15,0 -BRDA:15,0,0,- -DA:16,0 -BRDA:16,1,0,- -BRDA:16,1,1,- -DA:20,0 -FN:20,HookManager._uninstallHook -FNDA:0,HookManager._uninstallHook -DA:24,3 -FN:24,HookManager._preHook -FNDA:3,HookManager._preHook -DA:25,3 -BRDA:25,2,0,- -BRDA:25,2,1,3 -DA:26,3 -BRDA:26,3,0,- -DA:27,0 -DA:30,3 -FN:30,HookManager._postHook -FNDA:3,HookManager._postHook -DA:33,3 -BRDA:33,4,0,- -DA:34,0 -FNF:4 -FNH:2 -LF:11 -LH:5 -BRF:7 -BRH:1 -end_of_record -TN: -SF:src/core/ModuleManager.sol -DA:24,3 -FN:24,ModuleManager.onlyExecutor -FNDA:3,ModuleManager.onlyExecutor -DA:25,3 -DA:26,3 -DA:28,3 -DA:31,0 -FN:31,ModuleManager._initialized -FNDA:0,ModuleManager._initialized -DA:32,0 -DA:35,0 -FN:35,ModuleManager._installHash -FNDA:0,ModuleManager._installHash -DA:36,0 -DA:37,0 -DA:38,0 -DA:39,0 -DA:43,0 -DA:46,15 -FN:46,ModuleManager._installModule -FNDA:15,ModuleManager._installModule -DA:49,15 -DA:50,15 -BRDA:50,0,0,1 -BRDA:50,0,1,- -DA:51,1 -DA:52,14 -BRDA:52,1,0,14 -BRDA:52,1,1,- -DA:53,14 -DA:54,0 -BRDA:54,2,0,- -BRDA:54,2,1,- -DA:55,0 -DA:56,0 -BRDA:56,3,0,- -BRDA:56,3,1,- -DA:57,0 -DA:58,0 -BRDA:58,4,0,- -BRDA:58,4,1,- -DA:59,0 -DA:60,0 -BRDA:60,5,0,- -BRDA:60,5,1,- -DA:61,0 -DA:63,0 -DA:65,15 -DA:66,15 -DA:69,0 -FN:69,ModuleManager._install -FNDA:0,ModuleManager._install -DA:70,0 -DA:71,0 -DA:72,0 -DA:76,15 -FN:76,ModuleManager._install -FNDA:15,ModuleManager._install -DA:82,15 -DA:83,15 -DA:86,0 -FN:86,ModuleManager._uninstall -FNDA:0,ModuleManager._uninstall -DA:93,0 -DA:94,0 -FNF:7 -FNH:3 -LF:39 -LH:15 -BRF:12 -BRH:2 -end_of_record -TN: -SF:src/core/SelectorManager.sol -DA:26,0 -FN:26,SelectorManager.selectorConfig -FNDA:0,SelectorManager.selectorConfig -DA:27,0 -DA:30,0 -FN:30,SelectorManager._selectorConfig -FNDA:0,SelectorManager._selectorConfig -DA:31,0 -DA:34,0 -FN:34,SelectorManager._selectorStorage -FNDA:0,SelectorManager._selectorStorage -DA:35,0 -DA:37,0 -DA:41,0 -FN:41,SelectorManager._installSelector -FNDA:0,SelectorManager._installSelector -DA:42,0 -DA:43,0 -BRDA:43,0,0,- -BRDA:43,0,1,- -DA:44,0 -DA:45,0 -DA:46,0 -DA:47,0 -DA:48,0 -DA:49,0 -FNF:4 -FNH:0 -LF:16 -LH:0 -BRF:2 -BRH:0 -end_of_record -TN: -SF:src/core/ValidationManager.sol -DA:44,1 -FN:44,ValidationManager._validationStorage -FNDA:1,ValidationManager._validationStorage -DA:46,1 -DA:50,1 -FN:50,ValidationManager._installValidator -FNDA:1,ValidationManager._installValidator -DA:51,1 -BRDA:51,0,0,- -BRDA:51,0,1,1 -DA:52,1 -DA:53,1 -DA:56,0 -FN:56,ValidationManager._uninstallValidator -FNDA:0,ValidationManager._uninstallValidator -DA:59,0 -DA:60,0 -DA:63,0 -FN:63,ValidationManager._installPolicy -FNDA:0,ValidationManager._installPolicy -DA:64,0 -BRDA:64,1,0,- -BRDA:64,1,1,- -DA:65,0 -DA:66,0 -DA:67,0 -BRDA:67,2,0,- -BRDA:67,2,1,- -DA:68,0 -BRDA:68,3,0,- -BRDA:68,3,1,- -DA:69,0 -DA:70,0 -DA:72,0 -BRDA:72,4,0,- -BRDA:72,4,1,- -DA:74,0 -DA:77,0 -FN:77,ValidationManager._uninstallPolicy -FNDA:0,ValidationManager._uninstallPolicy -DA:80,0 -FN:80,ValidationManager._installSigner -FNDA:0,ValidationManager._installSigner -DA:81,0 -BRDA:81,5,0,- -BRDA:81,5,1,- -DA:82,0 -DA:83,0 -DA:84,0 -BRDA:84,6,0,- -BRDA:84,6,1,- -DA:85,0 -BRDA:85,7,0,- -BRDA:85,7,1,- -DA:86,0 -BRDA:86,8,0,- -BRDA:86,8,1,- -DA:87,0 -DA:88,0 -DA:90,0 -BRDA:90,9,0,- -BRDA:90,9,1,- -DA:92,0 -DA:94,0 -DA:97,0 -FN:97,ValidationManager._uninstallSigner -FNDA:0,ValidationManager._uninstallSigner -DA:100,0 -FN:100,ValidationManager._checkValidation -FNDA:0,ValidationManager._checkValidation -DA:101,0 -DA:102,0 -DA:103,0 -BRDA:103,10,0,- -BRDA:103,10,1,- -DA:104,0 -DA:106,0 -DA:107,0 -BRDA:107,11,0,- -BRDA:107,11,1,- -DA:111,0 -FN:111,ValidationManager._parseNonce -FNDA:0,ValidationManager._parseNonce -DA:120,0 -DA:121,0 -DA:122,0 -DA:126,0 -FN:126,ValidationManager._verifySignature -FNDA:0,ValidationManager._verifySignature -DA:131,0 -BRDA:131,12,0,- -DA:132,0 -DA:134,0 -DA:135,0 -DA:138,0 -FN:138,ValidationManager._validateUserOp -FNDA:0,ValidationManager._validateUserOp -DA:139,0 -BRDA:139,13,0,- -DA:140,0 -DA:144,0 -FN:144,ValidationManager._verify7702Signature -FNDA:0,ValidationManager._verify7702Signature -DA:145,0 -DA:148,0 -FN:148,ValidationManager._setRoot -FNDA:0,ValidationManager._setRoot -DA:149,0 -DA:150,0 -BRDA:150,14,0,- -BRDA:150,14,1,- -DA:151,0 -DA:152,0 -BRDA:152,15,0,- -BRDA:152,15,1,- -DA:153,0 -DA:155,0 -DA:157,0 -DA:160,0 -FN:160,ValidationManager._setRoot -FNDA:0,ValidationManager._setRoot -DA:161,0 -DA:162,0 -FNF:14 -FNH:2 -LF:65 -LH:6 -BRF:30 -BRH:1 -end_of_record -TN: -SF:test/Kernel.t.sol -DA:14,1 -FN:14,MockValidator.onInstall -FNDA:1,MockValidator.onInstall -DA:15,1 -DA:18,0 -FN:18,MockValidator.onUninstall -FNDA:0,MockValidator.onUninstall -DA:19,0 -DA:28,8 -FN:28,MockCallee.foo -FNDA:8,MockCallee.foo -DA:29,8 -DA:30,8 -DA:33,2 -FN:33,MockCallee.lorem -FNDA:2,MockCallee.lorem -DA:34,2 -DA:37,6 -FN:37,MockCallee.forceRevert -FNDA:6,MockCallee.forceRevert -DA:38,6 -FNF:5 -FNH:4 -LF:11 -LH:9 -BRF:0 -BRH:0 -end_of_record -TN: -SF:test/utils/EntryPointLib.sol -DA:11,14 -FN:11,EntryPointLib.deploy -FNDA:14,EntryPointLib.deploy -DA:12,14 -DA:13,14 -BRDA:13,0,0,- -BRDA:13,0,1,14 -DA:14,14 -FNF:1 -FNH:1 -LF:4 -LH:4 -BRF:2 -BRH:1 -end_of_record From f92365968c4829d39eba53424de717f936d5ca79 Mon Sep 17 00:00:00 2001 From: leekt Date: Thu, 22 May 2025 05:45:42 +0900 Subject: [PATCH 009/121] updated gitignore --- .gitignore | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/.gitignore b/.gitignore index 58c15b97..f9ff335c 100644 --- a/.gitignore +++ b/.gitignore @@ -13,4 +13,19 @@ docs/ # Dotenv file .env +lcov.info +coverage/ + +# node +node_modules/ + +# hardhat +artifacts/ +cache_hardhat/ +typechain-types/ + +# zerodev orchestra +log/ +.envrc + **/.DS_Store From f71d3e344853b902e2c96b6f121717f14ddcccb0 Mon Sep 17 00:00:00 2001 From: leekt Date: Thu, 22 May 2025 05:45:55 +0900 Subject: [PATCH 010/121] fmt --- src/Lib4337.sol | 17 +++++++---------- src/core/ExecutionManager.sol | 23 +++++++++++------------ src/core/ExecutorManager.sol | 5 +++-- src/core/HookManager.sol | 9 +++++---- src/core/ModuleManager.sol | 19 +++++++++---------- src/core/SelectorManager.sol | 1 - src/types/Constants.sol | 1 - src/types/Structs.sol | 2 -- 8 files changed, 35 insertions(+), 42 deletions(-) diff --git a/src/Lib4337.sol b/src/Lib4337.sol index 3518983a..ff829cb6 100644 --- a/src/Lib4337.sol +++ b/src/Lib4337.sol @@ -3,6 +3,7 @@ pragma solidity ^0.8.0; import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; import {UserOperationLib} from "account-abstraction/core/UserOperationLib.sol"; import {Eip7702Support} from "account-abstraction/core/Eip7702Support.sol"; + interface IERC5267 { function eip712Domain() external @@ -21,20 +22,16 @@ interface IERC5267 { library Lib4337 { bytes32 internal constant _DOMAIN_TYPEHASH_SANS_CHAIN_ID = 0x91ab3d17e3a50a9d89e63fd30b92be7f5336b03b287bb946787a83a9d62a2766; - function chainAgnosticUserOpHash(address ep, PackedUserOperation calldata userOp) public view returns(bytes32) { + + function chainAgnosticUserOpHash(address ep, PackedUserOperation calldata userOp) public view returns (bytes32) { bytes32 overrideInitCodeHash = Eip7702Support._getEip7702InitCodeHashOverride(userOp); - return - _hashTypedDataSansChainId(ep, UserOperationLib.hash(userOp, overrideInitCodeHash)); + return _hashTypedDataSansChainId(ep, UserOperationLib.hash(userOp, overrideInitCodeHash)); } - + /// @dev Variant of `_hashTypedData` that excludes the chain ID. /// Included for the niche use case of cross-chain workflows. - function _hashTypedDataSansChainId(address addr, bytes32 structHash) - internal - view - returns (bytes32 digest) - { - (,string memory name, string memory version, , , , ) = IERC5267(addr).eip712Domain(); + function _hashTypedDataSansChainId(address addr, bytes32 structHash) internal view returns (bytes32 digest) { + (, string memory name, string memory version,,,,) = IERC5267(addr).eip712Domain(); /// @solidity memory-safe-assembly assembly { let m := mload(0x40) // Load the free memory pointer. diff --git a/src/core/ExecutionManager.sol b/src/core/ExecutionManager.sol index ee3d174d..2d050e7a 100644 --- a/src/core/ExecutionManager.sol +++ b/src/core/ExecutionManager.sol @@ -8,20 +8,20 @@ abstract contract ExecutionManager { bytes1 callType = LibERC7579.getCallType(mode); bytes1 execType = LibERC7579.getExecType(mode); function() onRevert; - if(execType == LibERC7579.EXECTYPE_DEFAULT) { + if (execType == LibERC7579.EXECTYPE_DEFAULT) { onRevert = _onRevertThrow; - } else if(execType == LibERC7579.EXECTYPE_TRY) { + } else if (execType == LibERC7579.EXECTYPE_TRY) { onRevert = _onRevertSilent; } else { revert NotSupportedExecType(); } function(bytes calldata, function()) executeFunction; - if(callType == LibERC7579.CALLTYPE_SINGLE) { + if (callType == LibERC7579.CALLTYPE_SINGLE) { executeFunction = _executeCall; - } else if(callType == LibERC7579.CALLTYPE_BATCH) { + } else if (callType == LibERC7579.CALLTYPE_BATCH) { executeFunction = _executeBatchCall; - } else if(callType == LibERC7579.CALLTYPE_DELEGATECALL) { + } else if (callType == LibERC7579.CALLTYPE_DELEGATECALL) { executeFunction = _executeDelegateCall; } else { revert NotSupportedCallType(); @@ -32,7 +32,7 @@ abstract contract ExecutionManager { function _executeCall(bytes calldata executionData, function() onRevert) internal { (address target, uint256 value, bytes calldata data) = LibERC7579.decodeSingle(executionData); bool success = _call(target, value, data); - if(!success) { + if (!success) { onRevert(); } } @@ -40,7 +40,7 @@ abstract contract ExecutionManager { function _executeDelegateCall(bytes calldata executionData, function() onRevert) internal { (address delegate, bytes calldata data) = LibERC7579.decodeDelegate(executionData); bool success = _delegateCall(delegate, data); - if(!success) { + if (!success) { onRevert(); } } @@ -53,7 +53,7 @@ abstract contract ExecutionManager { for (uint256 i; i < length; i++) { (address target, uint256 value, bytes calldata data) = LibERC7579.getExecution(pointers, i); bool success = _call(target, value, data); - if(!success) { + if (!success) { onRevert(); } } @@ -68,10 +68,9 @@ abstract contract ExecutionManager { } } - function _onRevertSilent() internal { - } + function _onRevertSilent() internal {} - function _call(address target, uint256 value, bytes calldata callData) internal returns(bool success){ + function _call(address target, uint256 value, bytes calldata callData) internal returns (bool success) { /// @solidity memory-safe-assembly assembly { let ptr := mload(0x40) @@ -80,7 +79,7 @@ abstract contract ExecutionManager { } } - function _delegateCall(address delegate, bytes calldata callData) internal returns(bool success){ + function _delegateCall(address delegate, bytes calldata callData) internal returns (bool success) { /// @solidity memory-safe-assembly assembly { let ptr := mload(0x40) diff --git a/src/core/ExecutorManager.sol b/src/core/ExecutorManager.sol index 2d7e0a31..9e99a537 100644 --- a/src/core/ExecutorManager.sol +++ b/src/core/ExecutorManager.sol @@ -6,6 +6,7 @@ import "../interfaces/IERC7579Modules.sol"; contract ExecutorManager { error NotExecutor(); + struct ExecutorConfig { IHook hook; // address(1) : hook not required, address(0) : validator not installed } @@ -29,9 +30,9 @@ contract ExecutorManager { } function _installExecutor(address _executor, bytes calldata _internalData, bool _installSuccess) internal { - // NOTE: we don't care if install was successful + // NOTE: we don't care if install was successful address hook = _internalData.length >= 20 ? address(bytes20(_internalData[0:20])) : address(0); - if(hook == address(0)) { + if (hook == address(0)) { hook = address(1); // address(1) indicates it is installed and does not require any hook } _executorConfig(IExecutor(_executor)).hook = IHook(hook); diff --git a/src/core/HookManager.sol b/src/core/HookManager.sol index 8343069c..213779d3 100644 --- a/src/core/HookManager.sol +++ b/src/core/HookManager.sol @@ -12,7 +12,7 @@ import "../types/Error.sol"; abstract contract HookManager { function _installHook(address _hook, bytes calldata _internalData, bool _installSuccess) internal { - if(_internalData.length == 0) { + if (_internalData.length == 0) { require(_installSuccess, ModuleInstallFailed()); } } @@ -21,16 +21,17 @@ abstract contract HookManager { // no-op } - function _preHook(IHook _hook) internal returns(bytes memory context){ + function _preHook(IHook _hook) internal returns (bytes memory context) { require(address(_hook) != address(0), NotInstalled()); - if(address(_hook) != address(1)) { + if (address(_hook) != address(1)) { context = _hook.preCheck(msg.sender, msg.value, msg.data); } } + function _postHook(IHook _hook, bytes memory context) internal { // bool success, // bytes memory result - if(address(_hook) != address(1)) { + if (address(_hook) != address(1)) { _hook.postCheck(context); } } diff --git a/src/core/ModuleManager.sol b/src/core/ModuleManager.sol index d56e5827..d22892ca 100644 --- a/src/core/ModuleManager.sol +++ b/src/core/ModuleManager.sol @@ -10,7 +10,6 @@ import "../types/Events.sol"; import "../types/Structs.sol"; import "../types/Types.sol"; - function calldataKeccak(bytes calldata data) pure returns (bytes32 ret) { assembly ("memory-safe") { let mem := mload(0x40) @@ -21,15 +20,16 @@ function calldataKeccak(bytes calldata data) pure returns (bytes32 ret) { } contract ModuleManager is ValidationManager, ExecutorManager, HookManager, SelectorManager { - modifier onlyExecutor { + modifier onlyExecutor() { IHook hook = _executorConfig(IExecutor(msg.sender)).hook; bytes memory hookData = _preHook(hook); _; _postHook(hook, hookData); } - function _initialized() internal view returns(bool) { - return bytes3(address(this).code) == bytes3(0xef0100) || ValidationId.unwrap(_validationStorage().root) != bytes20(0); + function _initialized() internal view returns (bool) { + return bytes3(address(this).code) == bytes3(0xef0100) + || ValidationId.unwrap(_validationStorage().root) != bytes20(0); } function _installHash(Install[] calldata packages) internal pure returns (bytes32) { @@ -49,15 +49,15 @@ contract ModuleManager is ValidationManager, ExecutorManager, HookManager, Selec function(address, bytes calldata, bool) hook; if (moduleType == 1) { hook = _installValidator; - } else if(moduleType == 2) { + } else if (moduleType == 2) { hook = _installExecutor; - } else if(moduleType == 3) { + } else if (moduleType == 3) { hook = _installSelector; - } else if(moduleType == 4) { + } else if (moduleType == 4) { hook = _installHook; - } else if(moduleType == 5) { + } else if (moduleType == 5) { hook = _installPolicy; - } else if(moduleType == 6) { + } else if (moduleType == 6) { hook = _installSigner; } else { revert NotImplemented(); @@ -93,5 +93,4 @@ contract ModuleManager is ValidationManager, ExecutorManager, HookManager, Selec (bool success,) = module.call(abi.encodeWithSelector(IModule.onUninstall.selector, data)); hook(module, internalData, success); } - } diff --git a/src/core/SelectorManager.sol b/src/core/SelectorManager.sol index 7317edf0..5f2a05a0 100644 --- a/src/core/SelectorManager.sol +++ b/src/core/SelectorManager.sol @@ -12,7 +12,6 @@ import { import "../types/Error.sol"; abstract contract SelectorManager { - struct SelectorConfig { IHook hook; // 20 bytes for hook address address target; // 20 bytes target will be fallback module, called with call diff --git a/src/types/Constants.sol b/src/types/Constants.sol index f40c83de..64977f48 100644 --- a/src/types/Constants.sol +++ b/src/types/Constants.sol @@ -31,4 +31,3 @@ bytes32 constant HOOK_MANAGER_STORAGE_SLOT = 0x4605d5f70bb605094b2e761eccdc27bed // bytes32(uint256(keccak256('kernel.v3.validation')) - 1) bytes32 constant VALIDATION_MANAGER_STORAGE_SLOT = 0x7bcaa2ced2a71450ed5a9a1b4848e8e5206dbc3f06011e595f7f55428cc6f84f; bytes32 constant ERC1967_IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; - diff --git a/src/types/Structs.sol b/src/types/Structs.sol index 81b7706f..54b3f85a 100644 --- a/src/types/Structs.sol +++ b/src/types/Structs.sol @@ -1,4 +1,3 @@ - struct Install { uint256 moduleType; address module; @@ -11,4 +10,3 @@ struct Uninstall { address module; bytes data; } - From 5344bb466560cd3c55e9da346b0f8287a01bc663 Mon Sep 17 00:00:00 2001 From: leekt Date: Thu, 22 May 2025 05:50:29 +0900 Subject: [PATCH 011/121] temporary validator for validateUserOp --- src/Kernel.sol | 28 ++++++--- src/KernelFactory.sol | 7 ++- src/core/ValidationManager.sol | 6 ++ test/Kernel.t.sol | 109 ++++++++++++++++----------------- 4 files changed, 84 insertions(+), 66 deletions(-) diff --git a/src/Kernel.sol b/src/Kernel.sol index 80844e23..278c4819 100644 --- a/src/Kernel.sol +++ b/src/Kernel.sol @@ -80,7 +80,11 @@ contract Kernel is ModuleManager, ExecutionManager, EIP712 { function isValidSignature(bytes32 hash, bytes calldata signature) external view returns (bytes4) {} /// execution - function executeUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash) external payable onlyEntryPointOrSelf { + function executeUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash) + external + payable + onlyEntryPointOrSelf + { (bool success, bytes memory ret) = address(this).delegatecall(userOp.callData[4:]); } @@ -91,28 +95,28 @@ contract Kernel is ModuleManager, ExecutionManager, EIP712 { function executeFromExecutor(bytes32 mode, bytes calldata executionData) external payable onlyExecutor { _execute(mode, executionData); } - + function _fallback() internal { bytes4 selector = bytes4(msg.data); SelectorConfig storage $ = _selectorConfig(selector); - if($.target == address(0)) { + if ($.target == address(0)) { revert InvalidSelector(); } bytes memory hookData; - if(address($.hook) != address(0)) { + if (address($.hook) != address(0)) { hookData = _preHook($.hook); } bool success; - if($.callType == CallType.wrap(bytes1(0x00))) { + if ($.callType == CallType.wrap(bytes1(0x00))) { success = _call($.target, 0, msg.data); - } else if($.callType == CallType.wrap(bytes1(0xff))) { + } else if ($.callType == CallType.wrap(bytes1(0xff))) { success = _delegateCall($.target, msg.data); } - if(!success) { + if (!success) { _onRevertThrow(); } - if(address($.hook) != address(0)) { + if (address($.hook) != address(0)) { _postHook($.hook, hookData); } } @@ -123,7 +127,11 @@ contract Kernel is ModuleManager, ExecutionManager, EIP712 { bytes internalData; } - function installModule(uint256 moduleType, address module, bytes calldata initData) external payable onlyEntryPointOrSelf { + function installModule(uint256 moduleType, address module, bytes calldata initData) + external + payable + onlyEntryPointOrSelf + { InstallModuleDataFormat calldata imdf; assembly { imdf := initData.offset @@ -137,7 +145,7 @@ contract Kernel is ModuleManager, ExecutionManager, EIP712 { // NOTE : this ONLY allows root signature, for now function installModule(bool replayable, Install[] calldata packages, bytes calldata signature) external { - if(_initialized()) { + if (_initialized()) { // if 7702 or already initialized, use root signature to install module require(_verifyInstallSignature(replayable, packages, signature), InstallSignatureVerificationFailed()); _install(packages); diff --git a/src/KernelFactory.sol b/src/KernelFactory.sol index 2d742bc3..0c0a711c 100644 --- a/src/KernelFactory.sol +++ b/src/KernelFactory.sol @@ -17,7 +17,12 @@ contract KernelFactory { return Kernel(payable(account)); } - function deployWithAdditionalPackage(bytes calldata initData, bool replayable, Install[] calldata packages, bytes calldata signature) external payable returns (Kernel) { + function deployWithAdditionalPackage( + bytes calldata initData, + bool replayable, + Install[] calldata packages, + bytes calldata signature + ) external payable returns (Kernel) { bytes32 salt = keccak256(initData); (bool deployed, address account) = LibClone.createDeterministicERC1967(msg.value, address(template), salt); diff --git a/src/core/ValidationManager.sol b/src/core/ValidationManager.sol index 0cf26eb2..856ceee1 100644 --- a/src/core/ValidationManager.sol +++ b/src/core/ValidationManager.sol @@ -139,6 +139,12 @@ abstract contract ValidationManager { if(ValidationId.unwrap(vId) == bytes20(0)) { return _verify7702Signature(opHash, userOpSignature) ? 0 : 1; } + + // NOTE: removed permission for now, adding back after testing is done + address validator = address(ValidationId.unwrap(vId)); + PackedUserOperation memory modifiedOp = op; + modifiedOp.signature = userOpSignature; + return IValidator(validator).validateUserOp(modifiedOp, opHash); } function _verify7702Signature(bytes32 hash, bytes calldata sig) internal view returns (bool) { diff --git a/test/Kernel.t.sol b/test/Kernel.t.sol index 8f778756..f598dc53 100644 --- a/test/Kernel.t.sol +++ b/test/Kernel.t.sol @@ -23,8 +23,11 @@ contract MockValidator { contract MockCallee { uint256 public bar; string public data; + event Lorem(); + error Haha(); + function foo() external { bar++; emit Lorem(); @@ -38,11 +41,13 @@ contract MockCallee { revert Haha(); } } + struct Call { address target; uint256 value; bytes data; } + contract KernelTest is Test { IEntryPoint ep; KernelFactory factory; @@ -51,13 +56,13 @@ contract KernelTest is Test { MockCallee callee; address executor; - modifier unitTest { + modifier unitTest() { vm.startPrank(address(ep)); _; vm.stopPrank(); } - modifier unitTestExecutor { + modifier unitTestExecutor() { vm.startPrank(address(executor)); _; vm.stopPrank(); @@ -91,31 +96,31 @@ contract KernelTest is Test { function test_execute() external unitTest { vm.expectEmit(address(callee)); emit MockCallee.Lorem(); - kernel.execute(bytes32(0), abi.encodePacked(address(callee), uint256(0), abi.encodeWithSelector(MockCallee.foo.selector))); + kernel.execute( + bytes32(0), abi.encodePacked(address(callee), uint256(0), abi.encodeWithSelector(MockCallee.foo.selector)) + ); assertEq(callee.bar(), 1); } - + function test_execute_fail() external unitTest { vm.expectRevert(MockCallee.Haha.selector); - kernel.execute(bytes32(0), abi.encodePacked(address(callee), uint256(0), abi.encodeWithSelector(MockCallee.forceRevert.selector))); + kernel.execute( + bytes32(0), + abi.encodePacked(address(callee), uint256(0), abi.encodeWithSelector(MockCallee.forceRevert.selector)) + ); } - + function test_execute_fail_try() external unitTest { - kernel.execute(LibERC7579.encodeMode(bytes1(0x00), bytes1(0x01), bytes4(0), bytes22(0)), abi.encodePacked(address(callee), uint256(0), abi.encodeWithSelector(MockCallee.forceRevert.selector))); + kernel.execute( + LibERC7579.encodeMode(bytes1(0x00), bytes1(0x01), bytes4(0), bytes22(0)), + abi.encodePacked(address(callee), uint256(0), abi.encodeWithSelector(MockCallee.forceRevert.selector)) + ); } function test_execute_batch() external unitTest { Call[] memory calls = new Call[](2); - calls[0] = Call({ - target : address(callee), - value : 0, - data : abi.encodeWithSelector(MockCallee.foo.selector) - }); - calls[1] = Call({ - target : address(callee), - value : 0, - data : abi.encodeWithSelector(MockCallee.lorem.selector) - }); + calls[0] = Call({target: address(callee), value: 0, data: abi.encodeWithSelector(MockCallee.foo.selector)}); + calls[1] = Call({target: address(callee), value: 0, data: abi.encodeWithSelector(MockCallee.lorem.selector)}); assertEq(callee.data(), ""); vm.expectEmit(address(callee)); emit MockCallee.Lorem(); @@ -126,16 +131,9 @@ contract KernelTest is Test { function test_execute_batch_fail() external unitTest { Call[] memory calls = new Call[](2); - calls[0] = Call({ - target : address(callee), - value : 0, - data : abi.encodeWithSelector(MockCallee.foo.selector) - }); - calls[1] = Call({ - target : address(callee), - value : 0, - data : abi.encodeWithSelector(MockCallee.forceRevert.selector) - }); + calls[0] = Call({target: address(callee), value: 0, data: abi.encodeWithSelector(MockCallee.foo.selector)}); + calls[1] = + Call({target: address(callee), value: 0, data: abi.encodeWithSelector(MockCallee.forceRevert.selector)}); assertEq(callee.data(), ""); vm.expectRevert(MockCallee.Haha.selector); kernel.execute(LibERC7579.encodeMode(bytes1(0x01), bytes1(0x00), bytes4(0), bytes22(0)), abi.encode(calls)); @@ -143,16 +141,9 @@ contract KernelTest is Test { function test_execute_batch_fail_try() external unitTest { Call[] memory calls = new Call[](2); - calls[0] = Call({ - target : address(callee), - value : 0, - data : abi.encodeWithSelector(MockCallee.foo.selector) - }); - calls[1] = Call({ - target : address(callee), - value : 0, - data : abi.encodeWithSelector(MockCallee.forceRevert.selector) - }); + calls[0] = Call({target: address(callee), value: 0, data: abi.encodeWithSelector(MockCallee.foo.selector)}); + calls[1] = + Call({target: address(callee), value: 0, data: abi.encodeWithSelector(MockCallee.forceRevert.selector)}); assertEq(callee.data(), ""); kernel.execute(LibERC7579.encodeMode(bytes1(0x01), bytes1(0x01), bytes4(0), bytes22(0)), abi.encode(calls)); assertEq(callee.bar(), 1); @@ -161,41 +152,46 @@ contract KernelTest is Test { function test_execute_delegatecall() external unitTest { vm.expectEmit(address(kernel)); emit MockCallee.Lorem(); - kernel.execute(LibERC7579.encodeMode(bytes1(0xff), bytes1(0x00), bytes4(0), bytes22(0)), abi.encodePacked(address(callee), abi.encodeWithSelector(MockCallee.foo.selector))); + kernel.execute( + LibERC7579.encodeMode(bytes1(0xff), bytes1(0x00), bytes4(0), bytes22(0)), + abi.encodePacked(address(callee), abi.encodeWithSelector(MockCallee.foo.selector)) + ); } function test_execute_delegatecall_fail() external unitTest { vm.expectRevert(MockCallee.Haha.selector); - kernel.execute(LibERC7579.encodeMode(bytes1(0xff), bytes1(0x00), bytes4(0), bytes22(0)), abi.encodePacked(address(callee), abi.encodeWithSelector(MockCallee.forceRevert.selector))); + kernel.execute( + LibERC7579.encodeMode(bytes1(0xff), bytes1(0x00), bytes4(0), bytes22(0)), + abi.encodePacked(address(callee), abi.encodeWithSelector(MockCallee.forceRevert.selector)) + ); } - + function test_execute_delegatecall_fail_try() external unitTest { - kernel.execute(LibERC7579.encodeMode(bytes1(0xff), bytes1(0x01), bytes4(0), bytes22(0)), abi.encodePacked(address(callee), abi.encodeWithSelector(MockCallee.forceRevert.selector))); + kernel.execute( + LibERC7579.encodeMode(bytes1(0xff), bytes1(0x01), bytes4(0), bytes22(0)), + abi.encodePacked(address(callee), abi.encodeWithSelector(MockCallee.forceRevert.selector)) + ); } - + function test_execute_from_executor() external unitTestExecutor { vm.expectEmit(address(callee)); emit MockCallee.Lorem(); - kernel.executeFromExecutor(bytes32(0), abi.encodePacked(address(callee), uint256(0), abi.encodeWithSelector(MockCallee.foo.selector))); + kernel.executeFromExecutor( + bytes32(0), abi.encodePacked(address(callee), uint256(0), abi.encodeWithSelector(MockCallee.foo.selector)) + ); assertEq(callee.bar(), 1); } function test_execute_batch_from_executor() external unitTestExecutor { Call[] memory calls = new Call[](2); - calls[0] = Call({ - target : address(callee), - value : 0, - data : abi.encodeWithSelector(MockCallee.foo.selector) - }); - calls[1] = Call({ - target : address(callee), - value : 0, - data : abi.encodeWithSelector(MockCallee.lorem.selector) - }); + calls[0] = Call({target: address(callee), value: 0, data: abi.encodeWithSelector(MockCallee.foo.selector)}); + calls[1] = Call({target: address(callee), value: 0, data: abi.encodeWithSelector(MockCallee.lorem.selector)}); assertEq(callee.data(), ""); vm.expectEmit(address(callee)); emit MockCallee.Lorem(); - kernel.executeFromExecutor(LibERC7579.encodeMode(bytes1(0x01), bytes1(0x00), bytes4(0), bytes22(0)), abi.encode(calls)); + kernel.executeFromExecutor( + LibERC7579.encodeMode(bytes1(0x01), bytes1(0x00), bytes4(0), bytes22(0)), abi.encode(calls) + ); assertEq(callee.bar(), 1); assertEq(callee.data(), "lorem ipsum"); } @@ -203,6 +199,9 @@ contract KernelTest is Test { function test_execute_delegatecall_from_executor() external unitTestExecutor { vm.expectEmit(address(kernel)); emit MockCallee.Lorem(); - kernel.executeFromExecutor(LibERC7579.encodeMode(bytes1(0xff), bytes1(0x00), bytes4(0), bytes22(0)), abi.encodePacked(address(callee), abi.encodeWithSelector(MockCallee.foo.selector))); + kernel.executeFromExecutor( + LibERC7579.encodeMode(bytes1(0xff), bytes1(0x00), bytes4(0), bytes22(0)), + abi.encodePacked(address(callee), abi.encodeWithSelector(MockCallee.foo.selector)) + ); } } From 5affa76d3919f6ef8a46b7194289bcecbf8a06ae Mon Sep 17 00:00:00 2001 From: leekt Date: Thu, 22 May 2025 06:11:25 +0900 Subject: [PATCH 012/121] fmt with 1.2 --- src/Kernel.sol | 6 +++++- src/KernelFactory.sol | 17 ++++++++++++----- src/core/ValidationManager.sol | 27 ++++++++++++++------------- test/Kernel.t.sol | 9 +++++++-- 4 files changed, 38 insertions(+), 21 deletions(-) diff --git a/src/Kernel.sol b/src/Kernel.sol index 278c4819..2501375f 100644 --- a/src/Kernel.sol +++ b/src/Kernel.sol @@ -77,7 +77,11 @@ contract Kernel is ModuleManager, ExecutionManager, EIP712 { opHash = isReplayable(vMode) ? Lib4337.chainAgnosticUserOpHash(msg.sender, userOp) : userOpHash; } - function isValidSignature(bytes32 hash, bytes calldata signature) external view returns (bytes4) {} + function isValidSignature(bytes32 hash, bytes calldata signature) external view returns (bytes4) { + bool replayable = bytes1(signature[0]) == 0xff; + ValidationId vId = ValidationId.wrap(bytes20(signature[1:21])); + _verifySignature(vId, msg.sender, hash, signature[21:]); + } /// execution function executeUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash) diff --git a/src/KernelFactory.sol b/src/KernelFactory.sol index 0c0a711c..9464572a 100644 --- a/src/KernelFactory.sol +++ b/src/KernelFactory.sol @@ -11,22 +11,29 @@ contract KernelFactory { template = new Kernel(_entryPoint); } - function deploy(bytes calldata initData) external payable returns (Kernel) { - bytes32 salt = keccak256(initData); + function deploy(Install[] calldata initialPackages, uint256 nonce) external payable returns (Kernel) { + bytes32 salt = keccak256(abi.encode(initialPackages, nonce)); (bool deployed, address account) = LibClone.createDeterministicERC1967(msg.value, address(template), salt); - return Kernel(payable(account)); + Kernel k = Kernel(payable(account)); + if (deployed) { + return k; + } + k.installModule(true, initialPackages, hex""); + return k; } function deployWithAdditionalPackage( - bytes calldata initData, + Install[] calldata initialPackages, + uint256 nonce, bool replayable, Install[] calldata packages, bytes calldata signature ) external payable returns (Kernel) { - bytes32 salt = keccak256(initData); + bytes32 salt = keccak256(abi.encode(initialPackages, nonce)); (bool deployed, address account) = LibClone.createDeterministicERC1967(msg.value, address(template), salt); Kernel k = Kernel(payable(account)); + k.installModule(true, initialPackages, hex""); k.installModule(replayable, packages, signature); return k; } diff --git a/src/core/ValidationManager.sol b/src/core/ValidationManager.sol index 856ceee1..749d23a4 100644 --- a/src/core/ValidationManager.sol +++ b/src/core/ValidationManager.sol @@ -53,9 +53,7 @@ abstract contract ValidationManager { $.vInfo[ValidationId.wrap(bytes20(_validator))].vType = VALIDATION_TYPE_VALIDATOR; } - function _uninstallValidator(address _validator, bytes calldata _internalData, bool _uninstallSuccess) - internal - { + function _uninstallValidator(address _validator, bytes calldata _internalData, bool _uninstallSuccess) internal { ValidationStorage storage $ = _validationStorage(); $.vInfo[ValidationId.wrap(bytes20(_validator))].vType = VALIDATION_TYPE_VALIDATOR; } @@ -64,7 +62,7 @@ abstract contract ValidationManager { require(_installSuccess, ModuleInstallFailed()); ValidationStorage storage $ = _validationStorage(); ValidationId vId = ValidationId.wrap(bytes20(_internalData[0:20])); - if(installingPermission == ValidationId.wrap(bytes20(0))) { + if (installingPermission == ValidationId.wrap(bytes20(0))) { require(vId != ValidationId.wrap(bytes20(0)), "invalid validationId"); installingPermission = ValidationId.wrap(bytes20(_internalData[0:20])); $.vInfo[vId].vType = VALIDATION_TYPE_PERMISSION; @@ -74,14 +72,13 @@ abstract contract ValidationManager { $.vInfo[vId].policies.push(_policy); } - function _uninstallPolicy(address _policy, bytes calldata _internalData, bool _uninstallSuccess) internal { - } + function _uninstallPolicy(address _policy, bytes calldata _internalData, bool _uninstallSuccess) internal {} function _installSigner(address _signer, bytes calldata _internalData, bool _installSuccess) internal { require(_installSuccess, ModuleInstallFailed()); ValidationStorage storage $ = _validationStorage(); ValidationId vId = ValidationId.wrap(bytes20(_internalData[0:20])); - if(installingPermission == ValidationId.wrap(bytes20(0))) { + if (installingPermission == ValidationId.wrap(bytes20(0))) { require(vId != ValidationId.wrap(bytes20(0)), "invalid validationId"); require($.vInfo[vId].vType == ValidationType.wrap(0x00), "already taken"); installingPermission = ValidationId.wrap(bytes20(_internalData[0:20])); @@ -94,8 +91,7 @@ abstract contract ValidationManager { installingPermission = ValidationId.wrap(bytes20(0)); } - function _uninstallSigner(address _signer, bytes calldata _internalData, bool _uninstallSuccess) internal { - } + function _uninstallSigner(address _signer, bytes calldata _internalData, bool _uninstallSuccess) internal {} function _checkValidation(ValidationMode vMode, ValidationType vType, ValidationId vId) internal view { ValidationStorage storage $ = _validationStorage(); @@ -128,15 +124,20 @@ abstract contract ValidationManager { view returns (uint256 validationData) { - if(ValidationId.unwrap(vId) == bytes20(0)) { + if (ValidationId.unwrap(vId) == bytes20(0)) { return _verify7702Signature(_hash, _signature) ? 0 : 1; } IValidator validator = IValidator(getValidator(vId)); // TODO: add permission support; validator.isValidSignatureWithSender(requester, /*NOTE: fix this */ _hash, _signature); } - function _validateUserOp(ValidationId vId, bytes32 opHash, PackedUserOperation calldata op, bytes calldata userOpSignature) internal returns(uint256 validationData) { - if(ValidationId.unwrap(vId) == bytes20(0)) { + function _validateUserOp( + ValidationId vId, + bytes32 opHash, + PackedUserOperation calldata op, + bytes calldata userOpSignature + ) internal returns (uint256 validationData) { + if (ValidationId.unwrap(vId) == bytes20(0)) { return _verify7702Signature(opHash, userOpSignature) ? 0 : 1; } @@ -153,7 +154,7 @@ abstract contract ValidationManager { function _setRoot(Install calldata pkg) internal { ValidationId vId; - if(pkg.moduleType == 1) { + if (pkg.moduleType == 1) { vId = ValidationId.wrap(bytes20(pkg.module)); } else if (pkg.moduleType == 5 || pkg.moduleType == 6) { vId = ValidationId.wrap(bytes20(pkg.internalData[0:4])); diff --git a/test/Kernel.t.sol b/test/Kernel.t.sol index f598dc53..23ed4b3f 100644 --- a/test/Kernel.t.sol +++ b/test/Kernel.t.sol @@ -6,6 +6,7 @@ import {IEntryPoint} from "account-abstraction/interfaces/IEntryPoint.sol"; import {Kernel} from "src/Kernel.sol"; import {KernelFactory} from "src/KernelFactory.sol"; import {LibERC7579} from "solady/accounts/LibERC7579.sol"; +import {Install} from "src/types/Structs.sol"; contract MockValidator { event MockInstall(bytes data); @@ -78,7 +79,9 @@ contract KernelTest is Test { } function _initialize() internal { - kernel = factory.deploy(abi.encode("Kernel Test")); + Install[] memory pkgs = new Install[](1); + pkgs[0] = Install({moduleType: 1, module: address(mockValidator), moduleData: hex"", internalData: hex""}); + kernel = factory.deploy(pkgs, 0); vm.startPrank(address(ep)); kernel.installModule(2, executor, abi.encode(hex"", "")); @@ -86,7 +89,9 @@ contract KernelTest is Test { } function test_deploy() external unitTest { - Kernel k = factory.deploy(hex""); + Install[] memory pkgs = new Install[](1); + pkgs[0] = Install({moduleType: 1, module: address(mockValidator), moduleData: hex"", internalData: hex""}); + Kernel k = factory.deploy(pkgs, 1); } function test_install_validator() external unitTest { From d4737c6753415a57449ac0a351b94107e2646949 Mon Sep 17 00:00:00 2001 From: leekt Date: Sat, 24 May 2025 03:45:37 +0900 Subject: [PATCH 013/121] module test cases --- src/Kernel.sol | 29 +++-- src/core/ExecutionManager.sol | 14 ++- src/core/ExecutorManager.sol | 4 +- src/core/HookManager.sol | 16 ++- src/core/ModuleManager.sol | 27 ++++- src/core/SelectorManager.sol | 8 ++ src/core/ValidationManager.sol | 28 ++--- src/interfaces/IERC7579Account.sol | 108 ++++++++++++++++++ src/{ => lib}/Lib4337.sol | 0 src/types/Error.sol | 4 +- test/Kernel.t.sol | 177 +++++++++++++++++++++++++++++ test/mock/MockAction.sol | 19 ++++ test/mock/MockCallee.sol | 22 ++++ test/mock/MockERC1155.sol | 20 ++++ test/mock/MockERC20.sol | 22 ++++ test/mock/MockERC721.sol | 30 +++++ test/mock/MockExecutor.sol | 29 +++++ test/mock/MockFallback.sol | 76 +++++++++++++ test/mock/MockHook.sol | 40 +++++++ test/mock/MockPolicy.sol | 53 +++++++++ test/mock/MockSigner.sol | 54 +++++++++ test/mock/MockValidator.sol | 79 +++++++++++++ 22 files changed, 827 insertions(+), 32 deletions(-) create mode 100644 src/interfaces/IERC7579Account.sol rename src/{ => lib}/Lib4337.sol (100%) create mode 100644 test/mock/MockAction.sol create mode 100644 test/mock/MockCallee.sol create mode 100644 test/mock/MockERC1155.sol create mode 100644 test/mock/MockERC20.sol create mode 100644 test/mock/MockERC721.sol create mode 100644 test/mock/MockExecutor.sol create mode 100644 test/mock/MockFallback.sol create mode 100644 test/mock/MockHook.sol create mode 100644 test/mock/MockPolicy.sol create mode 100644 test/mock/MockSigner.sol create mode 100644 test/mock/MockValidator.sol diff --git a/src/Kernel.sol b/src/Kernel.sol index 2501375f..debeb73a 100644 --- a/src/Kernel.sol +++ b/src/Kernel.sol @@ -4,11 +4,12 @@ import {IEntryPoint} from "account-abstraction/interfaces/IEntryPoint.sol"; import {IAccount} from "account-abstraction/interfaces/IAccount.sol"; import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; import {IValidator} from "./interfaces/IERC7579Modules.sol"; -import "./types/Types.sol"; import {ModuleManager, Install} from "./core/ModuleManager.sol"; +import {parseNonce} from "./core/ValidationManager.sol"; import {ExecutionManager} from "./core/ExecutionManager.sol"; import {EIP712} from "solady/utils/EIP712.sol"; -import {Lib4337} from "./Lib4337.sol"; +import {Lib4337} from "./lib/Lib4337.sol"; +import "./types/Types.sol"; import "./types/Error.sol"; import "./types/Events.sol"; @@ -61,7 +62,7 @@ contract Kernel is ModuleManager, ExecutionManager, EIP712 { /* userOp.nonce = vMode | vType | vId */ - (ValidationMode vMode, ValidationType vType, ValidationId vId) = _parseNonce(userOp.nonce); + (ValidationMode vMode, ValidationType vType, ValidationId vId) = parseNonce(userOp.nonce); signature = userOp.signature; if (isEnable(vMode)) { bool enableReplayable = isEnableReplayable(vMode); @@ -100,8 +101,8 @@ contract Kernel is ModuleManager, ExecutionManager, EIP712 { _execute(mode, executionData); } - function _fallback() internal { - bytes4 selector = bytes4(msg.data); + function _fallback() internal returns (bytes memory res) { + bytes4 selector = bytes4(msg.data[0:4]); SelectorConfig storage $ = _selectorConfig(selector); if ($.target == address(0)) { revert InvalidSelector(); @@ -119,6 +120,8 @@ contract Kernel is ModuleManager, ExecutionManager, EIP712 { } if (!success) { _onRevertThrow(); + } else { + res = _getReturn(); } if (address($.hook) != address(0)) { _postHook($.hook, hookData); @@ -143,6 +146,18 @@ contract Kernel is ModuleManager, ExecutionManager, EIP712 { _installModule(moduleType, module, imdf.installData, imdf.internalData); } + function uninstallModule(uint256 moduleType, address module, bytes calldata initData) + external + payable + onlyEntryPointOrSelf + { + InstallModuleDataFormat calldata imdf; + assembly { + imdf := initData.offset + } + _uninstallModule(moduleType, module, imdf.installData, imdf.internalData); + } + function setRoot(ValidationId vId) external payable onlyEntryPointOrSelf { _setRoot(vId); } @@ -184,7 +199,7 @@ contract Kernel is ModuleManager, ExecutionManager, EIP712 { _verifySignature(vId, address(this), digest, signature); } - fallback() external payable { - _fallback(); + fallback(bytes calldata) external payable returns (bytes memory) { + return _fallback(); } } diff --git a/src/core/ExecutionManager.sol b/src/core/ExecutionManager.sol index 2d050e7a..73116b0c 100644 --- a/src/core/ExecutionManager.sol +++ b/src/core/ExecutionManager.sol @@ -13,7 +13,7 @@ abstract contract ExecutionManager { } else if (execType == LibERC7579.EXECTYPE_TRY) { onRevert = _onRevertSilent; } else { - revert NotSupportedExecType(); + revert InvalidExecType(); } function(bytes calldata, function()) executeFunction; @@ -24,7 +24,7 @@ abstract contract ExecutionManager { } else if (callType == LibERC7579.CALLTYPE_DELEGATECALL) { executeFunction = _executeDelegateCall; } else { - revert NotSupportedCallType(); + revert InvalidCallType(); } executeFunction(executionData, onRevert); } @@ -60,6 +60,16 @@ abstract contract ExecutionManager { } } + function _getReturn() internal returns (bytes memory result) { + assembly { + result := mload(0x40) + mstore(result, returndatasize()) // Store the length. + let o := add(result, 0x20) + returndatacopy(o, 0x00, returndatasize()) // Copy the returndata. + mstore(0x40, add(o, returndatasize())) // Allocate the memory. + } + } + function _onRevertThrow() internal { assembly { // Bubble up the revert if the call reverts. diff --git a/src/core/ExecutorManager.sol b/src/core/ExecutorManager.sol index 9e99a537..ee0e55b2 100644 --- a/src/core/ExecutorManager.sol +++ b/src/core/ExecutorManager.sol @@ -21,8 +21,8 @@ contract ExecutorManager { } } - function executorConfig(IExecutor executor) external view returns (ExecutorConfig memory) { - return _executorConfig(executor); + function executorConfig(address executor) external view returns (ExecutorConfig memory) { + return _executorConfig(IExecutor(executor)); } function _executorConfig(IExecutor executor) internal view returns (ExecutorConfig storage config) { diff --git a/src/core/HookManager.sol b/src/core/HookManager.sol index 213779d3..8dd81c5c 100644 --- a/src/core/HookManager.sol +++ b/src/core/HookManager.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.0; import {IHook, IFallback, IModule} from "../interfaces/IERC7579Modules.sol"; import {CallType} from "../types/Types.sol"; import { - SELECTOR_MANAGER_STORAGE_SLOT, + HOOK_MANAGER_STORAGE_SLOT, CALLTYPE_DELEGATECALL, CALLTYPE_SINGLE, MODULE_TYPE_FALLBACK @@ -11,14 +11,26 @@ import { import "../types/Error.sol"; abstract contract HookManager { + struct HookStorage { + mapping(address => bool) enabled; + } + + function _hookStorage() internal view returns (HookStorage storage hs) { + bytes32 slot = HOOK_MANAGER_STORAGE_SLOT; + assembly { + hs.slot := slot + } + } + function _installHook(address _hook, bytes calldata _internalData, bool _installSuccess) internal { if (_internalData.length == 0) { require(_installSuccess, ModuleInstallFailed()); } + _hookStorage().enabled[_hook] = true; } function _uninstallHook(address _hook, bytes calldata _internalData, bool _uninstallSuccess) internal { - // no-op + _hookStorage().enabled[_hook] = false; } function _preHook(IHook _hook) internal returns (bytes memory context) { diff --git a/src/core/ModuleManager.sol b/src/core/ModuleManager.sol index d22892ca..6a783d30 100644 --- a/src/core/ModuleManager.sol +++ b/src/core/ModuleManager.sol @@ -66,6 +66,32 @@ contract ModuleManager is ValidationManager, ExecutorManager, HookManager, Selec emit ModuleInstalled(moduleType, module); } + function _uninstallModule( + uint256 moduleType, + address module, + bytes calldata moduleData, + bytes calldata internalData + ) internal { + function(address, bytes calldata, bool) hook; + if (moduleType == 1) { + hook = _uninstallValidator; + } else if (moduleType == 2) { + hook = _uninstallExecutor; + } else if (moduleType == 3) { + hook = _uninstallSelector; + } else if (moduleType == 4) { + hook = _uninstallHook; + } else if (moduleType == 5) { + hook = _uninstallPolicy; + } else if (moduleType == 6) { + hook = _uninstallSigner; + } else { + revert NotImplemented(); + } + _uninstall(module, moduleData, internalData, hook); + emit ModuleInstalled(moduleType, module); + } + function _install(Install[] calldata packages) internal { for (uint256 i = 0; i < packages.length; i++) { Install calldata pkg = packages[i]; @@ -89,7 +115,6 @@ contract ModuleManager is ValidationManager, ExecutorManager, HookManager, Selec bytes calldata internalData, function(address, bytes calldata, bool) hook ) internal { - // TODO: make sure we use extra safe call (bool success,) = module.call(abi.encodeWithSelector(IModule.onUninstall.selector, data)); hook(module, internalData, success); } diff --git a/src/core/SelectorManager.sol b/src/core/SelectorManager.sol index 5f2a05a0..6510f4c2 100644 --- a/src/core/SelectorManager.sol +++ b/src/core/SelectorManager.sol @@ -47,4 +47,12 @@ abstract contract SelectorManager { $.callType = callType; $.hook = IHook(hook); } + + function _uninstallSelector(address _module, bytes calldata _internalData, bool _uninstallSuccess) internal { + bytes4 selector = bytes4(_internalData[0:4]); + SelectorConfig storage $ = _selectorConfig(selector); + $.target = address(0); + $.callType = CallType.wrap(bytes1(0x00)); + $.hook = IHook(address(0)); + } } diff --git a/src/core/ValidationManager.sol b/src/core/ValidationManager.sol index 749d23a4..773a3d25 100644 --- a/src/core/ValidationManager.sol +++ b/src/core/ValidationManager.sol @@ -38,6 +38,17 @@ function getType(ValidationId validator) pure returns (ValidationType vType) { } } +function parseNonce(uint256 nonce) pure returns (ValidationMode vMode, ValidationType vType, ValidationId vId) { + // 2bytes mode (1byte currentMode, 1byte type) + // 20bytes identifier + // 1byte mode | 1byte type | 20bytes vId | 2byte nonceKey | 8byte nonce == 32bytes + assembly { + vMode := nonce + vType := shl(8, nonce) + vId := shl(16, nonce) + } +} + abstract contract ValidationManager { ValidationId transient installingPermission; @@ -55,7 +66,7 @@ abstract contract ValidationManager { function _uninstallValidator(address _validator, bytes calldata _internalData, bool _uninstallSuccess) internal { ValidationStorage storage $ = _validationStorage(); - $.vInfo[ValidationId.wrap(bytes20(_validator))].vType = VALIDATION_TYPE_VALIDATOR; + $.vInfo[ValidationId.wrap(bytes20(_validator))].vType = VALIDATION_TYPE_ROOT; } function _installPolicy(address _policy, bytes calldata _internalData, bool _installSuccess) internal { @@ -104,21 +115,6 @@ abstract contract ValidationManager { } } - function _parseNonce(uint256 nonce) - internal - pure - returns (ValidationMode vMode, ValidationType vType, ValidationId vId) - { - // 2bytes mode (1byte currentMode, 1byte type) - // 20bytes identifier - // 1byte mode | 1byte type | 20bytes vId | 2byte nonceKey | 8byte nonce == 32bytes - assembly { - vMode := nonce - vType := shl(8, nonce) - vId := shl(16, nonce) - } - } - function _verifySignature(ValidationId vId, address requester, bytes32 _hash, bytes calldata _signature) internal view diff --git a/src/interfaces/IERC7579Account.sol b/src/interfaces/IERC7579Account.sol new file mode 100644 index 00000000..4ff76ec4 --- /dev/null +++ b/src/interfaces/IERC7579Account.sol @@ -0,0 +1,108 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.21; + +import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; + +struct Execution { + address target; + uint256 value; + bytes callData; +} + +interface IERC7579Account { + event ModuleInstalled(uint256 moduleTypeId, address module); + event ModuleUninstalled(uint256 moduleTypeId, address module); + + /** + * @dev Executes a transaction on behalf of the account. + * This function is intended to be called by ERC-4337 EntryPoint.sol + * @dev Ensure adequate authorization control: i.e. onlyEntryPointOrSelf + * + * @dev MSA MUST implement this function signature. + * If a mode is requested that is not supported by the Account, it MUST revert + * @param mode The encoded execution mode of the transaction. See ModeLib.sol for details + * @param executionCalldata The encoded execution call data + */ + function execute(bytes32 mode, bytes calldata executionCalldata) external payable; + + /** + * @dev Executes a transaction on behalf of the account. + * This function is intended to be called by Executor Modules + * @dev Ensure adequate authorization control: i.e. onlyExecutorModule + * + * @dev MSA MUST implement this function signature. + * If a mode is requested that is not supported by the Account, it MUST revert + * @param mode The encoded execution mode of the transaction. See ModeLib.sol for details + * @param executionCalldata The encoded execution call data + */ + function executeFromExecutor(bytes32 mode, bytes calldata executionCalldata) + external + payable + returns (bytes[] memory returnData); + + /** + * @dev ERC-1271 isValidSignature + * This function is intended to be used to validate a smart account signature + * and may forward the call to a validator module + * + * @param hash The hash of the data that is signed + * @param data The data that is signed + */ + function isValidSignature(bytes32 hash, bytes calldata data) external view returns (bytes4); + + /** + * @dev installs a Module of a certain type on the smart account + * @dev Implement Authorization control of your choosing + * @param moduleTypeId the module type ID according the ERC-7579 spec + * @param module the module address + * @param initData arbitrary data that may be required on the module during `onInstall` + * initialization. + */ + function installModule(uint256 moduleTypeId, address module, bytes calldata initData) external payable; + + /** + * @dev uninstalls a Module of a certain type on the smart account + * @dev Implement Authorization control of your choosing + * @param moduleTypeId the module type ID according the ERC-7579 spec + * @param module the module address + * @param deInitData arbitrary data that may be required on the module during `onUninstall` + * de-initialization. + */ + function uninstallModule(uint256 moduleTypeId, address module, bytes calldata deInitData) external payable; + + /** + * Function to check if the account supports a certain CallType or ExecType (see ModeLib.sol) + * @param encodedMode the encoded mode + */ + function supportsExecutionMode(bytes32 encodedMode) external view returns (bool); + + /** + * Function to check if the account supports installation of a certain module type Id + * @param moduleTypeId the module type ID according the ERC-7579 spec + */ + function supportsModule(uint256 moduleTypeId) external view returns (bool); + + /** + * Function to check if the account has a certain module installed + * @param moduleTypeId the module type ID according the ERC-7579 spec + * Note: keep in mind that some contracts can be multiple module types at the same time. It + * thus may be necessary to query multiple module types + * @param module the module address + * @param additionalContext additional context data that the smart account may interpret to + * identify conditions under which the module is installed. + * usually this is not necessary, but for some special hooks that + * are stored in mappings, this param might be needed + */ + function isModuleInstalled(uint256 moduleTypeId, address module, bytes calldata additionalContext) + external + view + returns (bool); + + /** + * @dev Returns the account id of the smart account + * @return accountImplementationId the account id of the smart account + * the accountId should be structured like so: + * "vendorname.accountname.semver" + */ + function accountId() external view returns (string memory accountImplementationId); +} diff --git a/src/Lib4337.sol b/src/lib/Lib4337.sol similarity index 100% rename from src/Lib4337.sol rename to src/lib/Lib4337.sol diff --git a/src/types/Error.sol b/src/types/Error.sol index 5803cc87..abe5a638 100644 --- a/src/types/Error.sol +++ b/src/types/Error.sol @@ -12,7 +12,7 @@ error NotInstalled(); error InstallSignatureVerificationFailed(); error InvalidRootValidation(); -error NotSupportedCallType(); -error NotSupportedExecType(); +error InvalidCallType(); +error InvalidExecType(); error InvalidSelector(); diff --git a/test/Kernel.t.sol b/test/Kernel.t.sol index 23ed4b3f..a7158588 100644 --- a/test/Kernel.t.sol +++ b/test/Kernel.t.sol @@ -4,9 +4,16 @@ import {Test} from "forge-std/Test.sol"; import {EntryPointLib} from "./utils/EntryPointLib.sol"; import {IEntryPoint} from "account-abstraction/interfaces/IEntryPoint.sol"; import {Kernel} from "src/Kernel.sol"; +import {SelectorManager} from "src/core/SelectorManager.sol"; import {KernelFactory} from "src/KernelFactory.sol"; import {LibERC7579} from "solady/accounts/LibERC7579.sol"; import {Install} from "src/types/Structs.sol"; +import {MockFallback} from "./mock/MockFallback.sol"; +import {MockExecutor} from "./mock/MockExecutor.sol"; +import {MockHook} from "./mock/MockHook.sol"; +import {IHook} from "src/interfaces/IERC7579Modules.sol"; +import {CallType} from "src/types/Types.sol"; +import "src/types/Error.sol"; contract MockValidator { event MockInstall(bytes data); @@ -55,6 +62,7 @@ contract KernelTest is Test { MockValidator mockValidator; Kernel kernel; MockCallee callee; + MockFallback mockFallback; address executor; modifier unitTest() { @@ -75,6 +83,7 @@ contract KernelTest is Test { mockValidator = new MockValidator(); callee = new MockCallee(); executor = makeAddr("Executor"); + mockFallback = new MockFallback(); _initialize(); } @@ -94,10 +103,162 @@ contract KernelTest is Test { Kernel k = factory.deploy(pkgs, 1); } + function test_install_executor_oninstall_success() external unitTest { + address newEx = address(new MockExecutor()); + kernel.installModule(2, newEx, abi.encode(hex"deadbeef", "")); + assertEq(address(kernel.executorConfig(newEx).hook), address(1)); + } + + function test_install_executor_oninstall_fail() external unitTest { + address newEx = makeAddr("New Executor"); + kernel.installModule(2, newEx, abi.encode(hex"", "")); + assertEq(address(kernel.executorConfig(newEx).hook), address(1)); + } + + function test_uninstall_executor_onuninstall_success() external unitTest { + address newEx = address(new MockExecutor()); + kernel.installModule(2, newEx, abi.encode(hex"deadbeef", "")); + assertEq(address(kernel.executorConfig(newEx).hook), address(1)); + kernel.uninstallModule(2, newEx, abi.encode(hex"", hex"")); + assertEq(address(kernel.executorConfig(newEx).hook), address(0)); + } + + function test_uninstall_executor_onuninstall_fail() external unitTest { + address newEx = makeAddr("New Executor"); + kernel.installModule(2, newEx, abi.encode(hex"", "")); + assertEq(address(kernel.executorConfig(newEx).hook), address(1)); + kernel.uninstallModule(2, newEx, abi.encode(hex"", hex"")); + assertEq(address(kernel.executorConfig(newEx).hook), address(0)); + } + + function test_install_hook() external unitTest { + MockHook mockHook = new MockHook(); + kernel.installModule(4, address(mockHook), abi.encode(hex"", "")); + } + + function test_uninstall_hook() external unitTest { + MockHook mockHook = new MockHook(); + kernel.installModule(4, address(mockHook), abi.encode(hex"", "")); + kernel.uninstallModule(4, address(mockHook), abi.encode(hex"", "")); + } + function test_install_validator() external unitTest { kernel.installModule(1, address(mockValidator), abi.encode(hex"deadbeef", "InternalData")); } + function test_install_selector_call() external unitTest { + kernel.installModule( + 3, + address(mockFallback), + abi.encode( + hex"deadbeef", abi.encodePacked(MockFallback.fallbackFunction.selector, bytes1(0x00), address(1)) + ) + ); + vm.expectEmit(address(mockFallback)); + emit MockFallback.Foobar(); + uint256 res = MockFallback(address(kernel)).fallbackFunction(10); + assertEq(res, 100); + SelectorManager.SelectorConfig memory c = kernel.selectorConfig(MockFallback.fallbackFunction.selector); + assertEq(address(c.target), address(mockFallback)); + assertEq(address(c.hook), address(1)); + assertTrue(c.callType == CallType.wrap(bytes1(0x00))); + } + + function test_install_selector_call_withhook() external unitTest { + MockHook mockHook = new MockHook(); + kernel.installModule(4, address(mockHook), abi.encode(hex"", "")); + kernel.installModule( + 3, + address(mockFallback), + abi.encode( + hex"deadbeef", abi.encodePacked(MockFallback.fallbackFunction.selector, bytes1(0x00), address(mockHook)) + ) + ); + vm.expectEmit(address(mockFallback)); + emit MockFallback.Foobar(); + uint256 res = MockFallback(address(kernel)).fallbackFunction(10); + assertEq(res, 100); + SelectorManager.SelectorConfig memory c = kernel.selectorConfig(MockFallback.fallbackFunction.selector); + assertEq(address(c.target), address(mockFallback)); + assertEq(address(c.hook), address(mockHook)); + assertTrue(c.callType == CallType.wrap(bytes1(0x00))); + } + + function test_uninstall_selector_call() external unitTest { + kernel.installModule( + 3, + address(mockFallback), + abi.encode( + hex"deadbeef", abi.encodePacked(MockFallback.fallbackFunction.selector, bytes1(0x00), address(1)) + ) + ); + vm.expectEmit(address(mockFallback)); + emit MockFallback.Foobar(); + uint256 res = MockFallback(address(kernel)).fallbackFunction(10); + assertEq(res, 100); + SelectorManager.SelectorConfig memory c = kernel.selectorConfig(MockFallback.fallbackFunction.selector); + assertEq(address(c.target), address(mockFallback)); + assertEq(address(c.hook), address(1)); + assertTrue(c.callType == CallType.wrap(bytes1(0x00))); + kernel.uninstallModule( + 3, address(mockFallback), abi.encode(hex"", abi.encodePacked(MockFallback.fallbackFunction.selector)) + ); + c = kernel.selectorConfig(MockFallback.fallbackFunction.selector); + assertEq(address(c.target), address(0)); + assertEq(address(c.hook), address(0)); + assertTrue(c.callType == CallType.wrap(bytes1(0x00))); + } + + function test_install_selector_call_fail() external unitTest { + kernel.installModule( + 3, + address(mockFallback), + abi.encode( + hex"deadbeef", abi.encodePacked(MockFallback.fallbackFunction.selector, bytes1(0x00), address(1)) + ) + ); + vm.expectRevert(MockFallback.Limit.selector, address(mockFallback)); + MockFallback(address(kernel)).fallbackFunction(100); + } + + function test_install_selector_delegatecall() external unitTest { + kernel.installModule( + 3, + address(mockFallback), + abi.encode( + hex"deadbeef", abi.encodePacked(MockFallback.fallbackFunction.selector, bytes1(0xff), address(1)) + ) + ); + vm.expectEmit(address(kernel)); + emit MockFallback.Foobar(); + uint256 res = MockFallback(address(kernel)).fallbackFunction(10); + assertEq(res, 100); + } + + function test_install_selector_delegatecall_fail() external unitTest { + kernel.installModule( + 3, + address(mockFallback), + abi.encode( + hex"deadbeef", abi.encodePacked(MockFallback.fallbackFunction.selector, bytes1(0xff), address(1)) + ) + ); + vm.expectRevert(MockFallback.Limit.selector, address(kernel)); + MockFallback(address(kernel)).fallbackFunction(100); + } + + function test_install_selector_invalid_selector() external unitTest { + kernel.installModule( + 3, + address(mockFallback), + abi.encode( + hex"deadbeef", abi.encodePacked(MockFallback.fallbackFunction.selector, bytes1(0xff), address(1)) + ) + ); + vm.expectRevert(InvalidSelector.selector, address(kernel)); + MockFallback(address(kernel)).getData(); + } + function test_execute() external unitTest { vm.expectEmit(address(callee)); emit MockCallee.Lorem(); @@ -115,6 +276,22 @@ contract KernelTest is Test { ); } + function test_execute_fail_invalid_callType() external unitTest { + vm.expectRevert(InvalidCallType.selector, address(kernel)); + kernel.execute( + LibERC7579.encodeMode(bytes1(0x02), bytes1(0x01), bytes4(0), bytes22(0)), + abi.encodePacked(address(callee), uint256(0), abi.encodeWithSelector(MockCallee.foo.selector)) + ); + } + + function test_execute_fail_invalid_execType() external unitTest { + vm.expectRevert(InvalidExecType.selector, address(kernel)); + kernel.execute( + LibERC7579.encodeMode(bytes1(0x00), bytes1(0x02), bytes4(0), bytes22(0)), + abi.encodePacked(address(callee), uint256(0), abi.encodeWithSelector(MockCallee.foo.selector)) + ); + } + function test_execute_fail_try() external unitTest { kernel.execute( LibERC7579.encodeMode(bytes1(0x00), bytes1(0x01), bytes4(0), bytes22(0)), diff --git a/test/mock/MockAction.sol b/test/mock/MockAction.sol new file mode 100644 index 00000000..dd31e1dc --- /dev/null +++ b/test/mock/MockAction.sol @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +contract MockAction { + event MockActionEvent(address here); + + function onInstall(bytes calldata data) external payable {} + + function onUninstall(bytes calldata data) external payable {} + + function isModuleType(uint256 moduleTypeId) external view returns (bool) {} + + function isInitialized(address smartAccount) external view returns (bool) {} + + function doSomething() external { + emit MockActionEvent(address(this)); + } +} diff --git a/test/mock/MockCallee.sol b/test/mock/MockCallee.sol new file mode 100644 index 00000000..edcc99e4 --- /dev/null +++ b/test/mock/MockCallee.sol @@ -0,0 +1,22 @@ +pragma solidity ^0.8.0; + +contract MockCallee { + uint256 public value; + + event MockEvent(address indexed caller, address indexed here); + + function setValue(uint256 _value) public { + value = _value; + } + + function addValue(uint256 _value) public { + value += _value; + } + + function emitEvent(bool shouldFail) public { + if (shouldFail) { + revert("Hello"); + } + emit MockEvent(msg.sender, address(this)); + } +} diff --git a/test/mock/MockERC1155.sol b/test/mock/MockERC1155.sol new file mode 100644 index 00000000..cf758e2a --- /dev/null +++ b/test/mock/MockERC1155.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import "solady/tokens/ERC1155.sol"; + +contract MockERC1155 is ERC1155 { + function test_ignore() public {} + + function uri(uint256) public pure override returns (string memory) { + return "https://example.com"; + } + + function mint(address to, uint256 id, uint256 amount, bytes memory data) public { + _mint(to, id, amount, data); + } + + function batchMint(address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data) public { + _batchMint(to, ids, amounts, data); + } +} diff --git a/test/mock/MockERC20.sol b/test/mock/MockERC20.sol new file mode 100644 index 00000000..18410054 --- /dev/null +++ b/test/mock/MockERC20.sol @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import "solady/tokens/ERC20.sol"; + +contract MockERC20 is ERC20 { + constructor() ERC20() {} + + function test_ignore() public {} + + function name() public pure override returns (string memory) { + return "MockERC20"; + } + + function symbol() public pure override returns (string memory) { + return "MOCK"; + } + + function mint(address _to, uint256 _amount) external { + _mint(_to, _amount); + } +} diff --git a/test/mock/MockERC721.sol b/test/mock/MockERC721.sol new file mode 100644 index 00000000..4cc30766 --- /dev/null +++ b/test/mock/MockERC721.sol @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import "solady/tokens/ERC721.sol"; + +contract MockERC721 is ERC721 { + constructor() ERC721() {} + + function test_ignore() public {} + + function name() public pure override returns (string memory) { + return "MockERC721"; + } + + function symbol() public pure override returns (string memory) { + return "MOCK"; + } + + function tokenURI(uint256) public pure override returns (string memory) { + return ""; + } + + function mint(address _to, uint256 _id) external { + _mint(_to, _id); + } + + function safeMint(address _to, uint256 _id) external { + _safeMint(_to, _id); + } +} diff --git a/test/mock/MockExecutor.sol b/test/mock/MockExecutor.sol new file mode 100644 index 00000000..64eff851 --- /dev/null +++ b/test/mock/MockExecutor.sol @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {IExecutor} from "src/interfaces/IERC7579Modules.sol"; +import {IERC7579Account} from "src/interfaces/IERC7579Account.sol"; + +contract MockExecutor is IExecutor { + mapping(address => bytes) public data; + + function onInstall(bytes calldata _data) external payable override { + data[msg.sender] = _data; + } + + function onUninstall(bytes calldata) external payable override { + delete data[msg.sender]; + } + + function isModuleType(uint256 moduleTypeId) external pure override returns (bool) { + return moduleTypeId == 2; + } + + function isInitialized(address smartAccount) external view override returns (bool) { + return data[smartAccount].length > 0; + } + + function sudoDoExec(IERC7579Account account, bytes32 mode, bytes calldata executionCalldata) external payable { + account.executeFromExecutor(mode, executionCalldata); + } +} diff --git a/test/mock/MockFallback.sol b/test/mock/MockFallback.sol new file mode 100644 index 00000000..d566fd02 --- /dev/null +++ b/test/mock/MockFallback.sol @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {IERC7579Account} from "src/interfaces/IERC7579Account.sol"; +import {IFallback} from "src/interfaces/IERC7579Modules.sol"; +import {CallType, ExecType, ExecMode} from "src/types/Types.sol"; + +contract Callee { + address public lastCaller; + + function calleeTest() external { + lastCaller = msg.sender; + } +} + +contract MockFallback is IFallback { + event Foobar(); + + error Limit(); + + mapping(address => bytes) public data; + + uint256 public valueStored; + + bool isExecutor; + + Callee public callee; + + constructor() { + callee = new Callee(); + } + + function setExecutorMode(bool _isExecutor) external payable { + isExecutor = _isExecutor; + } + + function onInstall(bytes calldata _data) external payable override { + data[msg.sender] = _data; + } + + function onUninstall(bytes calldata) external payable override { + delete data[msg.sender]; + } + + function isModuleType(uint256 moduleTypeId) external view override returns (bool) { + return moduleTypeId == 3 || (isExecutor && moduleTypeId == 2); + } + + function isInitialized(address smartAccount) external view override returns (bool) { + return data[smartAccount].length > 0; + } + + function fallbackFunction(uint256 v) external returns (uint256) { + require(v < 100, Limit()); + emit Foobar(); + return v * v; + } + + function getData() external view returns (bytes memory) { + return data[msg.sender]; + } + + function getCaller() external pure returns (address) { + return address(bytes20(msg.data[msg.data.length - 20:])); + } + + function setData(uint256 value) external { + valueStored = value; + if (isExecutor) { + IERC7579Account(msg.sender).executeFromExecutor( + bytes32(0), + abi.encodePacked(address(callee), uint256(0), abi.encodeWithSelector(Callee.calleeTest.selector)) + ); + } + } +} diff --git a/test/mock/MockHook.sol b/test/mock/MockHook.sol new file mode 100644 index 00000000..da2fb400 --- /dev/null +++ b/test/mock/MockHook.sol @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {IHook} from "src/interfaces/IERC7579Modules.sol"; + +contract MockHook is IHook { + mapping(address => bytes) public data; + mapping(address => bytes) public preHookData; + mapping(address => bytes) public postHookData; + + function onInstall(bytes calldata _data) external payable override { + data[msg.sender] = _data; + } + + function onUninstall(bytes calldata) external payable override { + delete data[msg.sender]; + } + + function isModuleType(uint256 moduleTypeId) external pure override returns (bool) { + return moduleTypeId == 1; + } + + function isInitialized(address smartAccount) external view override returns (bool) { + return data[smartAccount].length > 0; + } + + function preCheck(address msgSender, uint256 value, bytes calldata msgData) + external + payable + override + returns (bytes memory hookData) + { + preHookData[msg.sender] = abi.encodePacked(msgSender, msgData); + return data[msg.sender]; + } + + function postCheck(bytes calldata hookData) external payable override { + postHookData[msg.sender] = hookData; + } +} diff --git a/test/mock/MockPolicy.sol b/test/mock/MockPolicy.sol new file mode 100644 index 00000000..a67d1897 --- /dev/null +++ b/test/mock/MockPolicy.sol @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import {IPolicy} from "src/interfaces/IERC7579Modules.sol"; +import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; +import "forge-std/console.sol"; + +contract MockPolicy is IPolicy { + mapping(address => mapping(bytes32 => bool)) public pass; + mapping(address => bytes) public installData; + mapping(address => mapping(bytes32 => bytes)) public sig; + + function onInstall(bytes calldata data) external payable override { + installData[msg.sender] = data; + } + + function onUninstall(bytes calldata) external payable override {} + + function sudoSetValidSig(address _wallet, bytes32 _id, bytes calldata _sig) external payable { + sig[_wallet][_id] = _sig; + } + + function sudoSetPass(address _wallet, bytes32 _id, bool _pass) external payable { + pass[_wallet][_id] = _pass; + } + + function isModuleType(uint256 moduleTypeId) external pure override returns (bool) { + return moduleTypeId == 5; + } + + function isInitialized(address smartAccount) external view override returns (bool) { + return installData[smartAccount].length > 0; + } + + function checkUserOpPolicy(bytes32 id, PackedUserOperation calldata userOp) + external + payable + override + returns (uint256) + { + return keccak256(userOp.signature) == keccak256(sig[msg.sender][id]) ? 0 : 1; + } + + function checkSignaturePolicy(bytes32 id, address, bytes32, bytes calldata) + external + view + override + returns (uint256) + { + return pass[msg.sender][id] ? 0 : 1; + } +} diff --git a/test/mock/MockSigner.sol b/test/mock/MockSigner.sol new file mode 100644 index 00000000..5d76f18b --- /dev/null +++ b/test/mock/MockSigner.sol @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "src/interfaces/IERC7579Modules.sol"; + +contract MockSigner is ISigner { + mapping(address wallet => bytes) public data; + mapping(address => mapping(bytes32 => bytes)) public sig; + mapping(address => mapping(bytes32 => bool)) public pass; + + function sudoSetValidSig(address _wallet, bytes32 _id, bytes calldata _sig) external payable { + sig[_wallet][_id] = _sig; + } + + function sudoSetPass(address _wallet, bytes32 _id, bool _flag) external payable { + pass[_wallet][_id] = _flag; + } + + function onInstall(bytes calldata _data) external payable override { + data[msg.sender] = _data; + } + + function onUninstall(bytes calldata) external payable override {} + + function isModuleType(uint256 moduleTypeId) external pure override returns (bool) { + if (moduleTypeId == 7) { + return true; + } else { + return false; + } + } + + function isInitialized(address smartAccount) external view override returns (bool) { + return data[smartAccount].length > 0; + } + + function checkUserOpSignature(bytes32 id, PackedUserOperation calldata userOp, bytes32) + external + payable + override + returns (uint256) + { + return keccak256(userOp.signature) == keccak256(sig[msg.sender][id]) ? 0 : 1; + } + + function checkSignature(bytes32 id, address, bytes32, bytes calldata) external view override returns (bytes4) { + if (pass[msg.sender][id] == true) { + return 0x1626ba7e; + } else { + return 0xffffffff; + } + } +} diff --git a/test/mock/MockValidator.sol b/test/mock/MockValidator.sol new file mode 100644 index 00000000..997fb4ff --- /dev/null +++ b/test/mock/MockValidator.sol @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "src/interfaces/IERC7579Modules.sol"; + +contract MockValidator is IValidator, IHook { + mapping(address => bool) public initialized; + bool public success; + uint256 public count; + + mapping(address => bytes) public validatorData; + mapping(bytes32 => bool) public validSig; + + bool public isHook; + + function setHook(bool _isHook) external { + isHook = _isHook; + } + + function sudoSetSuccess(bool _success) external { + success = _success; + } + + function sudoSetValidSig(bytes calldata sig) external { + validSig[keccak256(sig)] = true; + } + + function onInstall(bytes calldata data) external payable { + initialized[msg.sender] = true; + validatorData[msg.sender] = data; + } + + function onUninstall(bytes calldata data) external payable { + initialized[msg.sender] = false; + validatorData[msg.sender] = data; + } + + function isModuleType(uint256 typeID) external pure returns (bool) { + return typeID == 1; + } + + /** + * @dev Returns if the module was already initialized for a provided smartaccount + */ + function isInitialized(address smartAccount) external view returns (bool) { + return initialized[smartAccount]; + } + + function validateUserOp(PackedUserOperation calldata, bytes32) external payable returns (uint256) { + count++; + + if (success) { + return 0; + } else { + return 1; + } + } + + function isValidSignatureWithSender(address, bytes32, bytes calldata sig) external view returns (bytes4) { + if (validSig[keccak256(sig)] == true) { + return 0x1626ba7e; + } else { + return 0xffffffff; + } + } + + function preCheck(address msgSender, uint256 value, bytes calldata msgData) + external + payable + returns (bytes memory hookData) + { + return hex""; + } + + function postCheck(bytes calldata hookData) external payable { + return; + } +} From 828fa8f61c1a122e947da4c5cb0ea9a3f1c034c1 Mon Sep 17 00:00:00 2001 From: leekt Date: Sat, 24 May 2025 04:08:35 +0900 Subject: [PATCH 014/121] userop test case --- src/Kernel.sol | 2 +- src/core/ValidationManager.sol | 4 +-- test/Kernel.t.sol | 54 ++++++++++++++++++++++++++-------- 3 files changed, 43 insertions(+), 17 deletions(-) diff --git a/src/Kernel.sol b/src/Kernel.sol index debeb73a..553aedfc 100644 --- a/src/Kernel.sol +++ b/src/Kernel.sol @@ -74,7 +74,7 @@ contract Kernel is ModuleManager, ExecutionManager, EIP712 { _install(sig.packages); signature = sig.userOpSignature; } - _checkValidation(vMode, vType, vId); + verifier = _checkValidation(vMode, vType, vId); opHash = isReplayable(vMode) ? Lib4337.chainAgnosticUserOpHash(msg.sender, userOp) : userOpHash; } diff --git a/src/core/ValidationManager.sol b/src/core/ValidationManager.sol index 773a3d25..566d6299 100644 --- a/src/core/ValidationManager.sol +++ b/src/core/ValidationManager.sol @@ -104,9 +104,8 @@ abstract contract ValidationManager { function _uninstallSigner(address _signer, bytes calldata _internalData, bool _uninstallSuccess) internal {} - function _checkValidation(ValidationMode vMode, ValidationType vType, ValidationId vId) internal view { + function _checkValidation(ValidationMode vMode, ValidationType vType, ValidationId vId) internal view returns(ValidationId v) { ValidationStorage storage $ = _validationStorage(); - ValidationId v; if (vType == VALIDATION_TYPE_ROOT) { v = $.root; } else { @@ -136,7 +135,6 @@ abstract contract ValidationManager { if (ValidationId.unwrap(vId) == bytes20(0)) { return _verify7702Signature(opHash, userOpSignature) ? 0 : 1; } - // NOTE: removed permission for now, adding back after testing is done address validator = address(ValidationId.unwrap(vId)); PackedUserOperation memory modifiedOp = op; diff --git a/test/Kernel.t.sol b/test/Kernel.t.sol index a7158588..1911d500 100644 --- a/test/Kernel.t.sol +++ b/test/Kernel.t.sol @@ -3,6 +3,7 @@ pragma solidity ^0.8.0; import {Test} from "forge-std/Test.sol"; import {EntryPointLib} from "./utils/EntryPointLib.sol"; import {IEntryPoint} from "account-abstraction/interfaces/IEntryPoint.sol"; +import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; import {Kernel} from "src/Kernel.sol"; import {SelectorManager} from "src/core/SelectorManager.sol"; import {KernelFactory} from "src/KernelFactory.sol"; @@ -10,24 +11,12 @@ import {LibERC7579} from "solady/accounts/LibERC7579.sol"; import {Install} from "src/types/Structs.sol"; import {MockFallback} from "./mock/MockFallback.sol"; import {MockExecutor} from "./mock/MockExecutor.sol"; +import {MockValidator} from "./mock/MockValidator.sol"; import {MockHook} from "./mock/MockHook.sol"; import {IHook} from "src/interfaces/IERC7579Modules.sol"; import {CallType} from "src/types/Types.sol"; import "src/types/Error.sol"; -contract MockValidator { - event MockInstall(bytes data); - event MockUninstall(bytes data); - - function onInstall(bytes calldata data) external payable { - emit MockInstall(data); - } - - function onUninstall(bytes calldata data) external payable { - emit MockUninstall(data); - } -} - contract MockCallee { uint256 public bar; string public data; @@ -64,6 +53,7 @@ contract KernelTest is Test { MockCallee callee; MockFallback mockFallback; address executor; + address payable beneficiary; modifier unitTest() { vm.startPrank(address(ep)); @@ -77,6 +67,10 @@ contract KernelTest is Test { vm.stopPrank(); } + modifier entryPointTest() { + _; + } + function setUp() external { ep = EntryPointLib.deploy(); factory = new KernelFactory(ep); @@ -84,6 +78,7 @@ contract KernelTest is Test { callee = new MockCallee(); executor = makeAddr("Executor"); mockFallback = new MockFallback(); + beneficiary = payable(makeAddr("Beneficiary")); _initialize(); } @@ -91,12 +86,45 @@ contract KernelTest is Test { Install[] memory pkgs = new Install[](1); pkgs[0] = Install({moduleType: 1, module: address(mockValidator), moduleData: hex"", internalData: hex""}); kernel = factory.deploy(pkgs, 0); + vm.deal(address(kernel), 1e18); vm.startPrank(address(ep)); kernel.installModule(2, executor, abi.encode(hex"", "")); vm.stopPrank(); } + function encodeNonce(bool replayableUserOp, bool enableFlag, bool replayableEnable, bytes1 vType, bytes20 vId) internal returns(uint256 nonce) { + uint8 uMode = 0; + if(replayableEnable) { + uMode += 2**6; + } + if(enableFlag) { + uMode += 2**3; + } + if(replayableEnable) { + uMode += 2**2; + } + uint192 key = uint192(bytes24(abi.encodePacked(uMode, vType, vId, bytes2(0x00)))); + return ep.getNonce(address(kernel), key); + } + + function test_userop() external entryPointTest { + PackedUserOperation[] memory ops = new PackedUserOperation[](1); + ops[0] = PackedUserOperation({ + sender: address(kernel), + nonce : encodeNonce(false, false, false, bytes1(0), bytes20(0)), + initCode : hex"", + callData : abi.encodeWithSelector(Kernel.execute.selector, bytes32(0), abi.encodePacked(address(callee), MockCallee.foo.selector)), + accountGasLimits: bytes32(abi.encodePacked(uint128(1000000), uint128(1000000))), // TODO make this dynamic + preVerificationGas: 1000000, + gasFees: bytes32(abi.encodePacked(uint128(1), uint128(1))), + paymasterAndData: hex"", + signature: hex"" + }); + mockValidator.sudoSetSuccess(true); + ep.handleOps(ops, beneficiary); + } + function test_deploy() external unitTest { Install[] memory pkgs = new Install[](1); pkgs[0] = Install({moduleType: 1, module: address(mockValidator), moduleData: hex"", internalData: hex""}); From a9fe29a99c36684f33cd8ea666984ee5af763a79 Mon Sep 17 00:00:00 2001 From: leekt Date: Tue, 27 May 2025 19:32:57 +0900 Subject: [PATCH 015/121] uninstall policy/signer --- foundry.toml | 1 + lib/forge-std | 2 +- lib/solady | 2 +- src/Kernel.sol | 52 +++- src/core/ModuleManager.sol | 8 +- src/core/ValidationManager.sol | 178 ++++++++--- src/lib/Lib4337.sol | 57 +++- src/types/Constants.sol | 5 + src/types/Error.sol | 9 + src/types/Events.sol | 2 + src/types/Structs.sol | 15 + src/types/Types.sol | 35 ++- test/Kernel.t.sol | 537 ++++++++++++++++++++++++++++++++- 13 files changed, 814 insertions(+), 89 deletions(-) diff --git a/foundry.toml b/foundry.toml index 25b918f9..83816a21 100644 --- a/foundry.toml +++ b/foundry.toml @@ -2,5 +2,6 @@ src = "src" out = "out" libs = ["lib"] +via_ir = true # See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options diff --git a/lib/forge-std b/lib/forge-std index 3b20d60d..f46d8301 160000 --- a/lib/forge-std +++ b/lib/forge-std @@ -1 +1 @@ -Subproject commit 3b20d60d14b343ee4f908cb8079495c07f5e8981 +Subproject commit f46d8301cf732f4f83846565aa475628265e51e0 diff --git a/lib/solady b/lib/solady index bf973bd7..b609a9c7 160000 --- a/lib/solady +++ b/lib/solady @@ -1 +1 @@ -Subproject commit bf973bd715908728ea81e49100629f7f26ecf566 +Subproject commit b609a9c79ce541c2beca7a7d247665e7c93942a3 diff --git a/src/Kernel.sol b/src/Kernel.sol index 553aedfc..bae6f982 100644 --- a/src/Kernel.sol +++ b/src/Kernel.sol @@ -12,12 +12,13 @@ import {Lib4337} from "./lib/Lib4337.sol"; import "./types/Types.sol"; import "./types/Error.sol"; import "./types/Events.sol"; +import "./types/Constants.sol"; + +import "forge-std/console.sol"; contract Kernel is ModuleManager, ExecutionManager, EIP712 { IEntryPoint immutable entryPoint; - error Unauthorized(); - modifier onlyEntryPointOrSelf() { require(msg.sender == address(entryPoint) || msg.sender == address(this), Unauthorized()); _; @@ -45,8 +46,14 @@ contract Kernel is ModuleManager, ExecutionManager, EIP712 { onlyEntryPointOrSelf returns (uint256 validationData) { - (ValidationId verifier, bytes32 opHash, bytes calldata userOpSignature) = _processUserOp(userOp, userOpHash); - validationData = _validateUserOp(verifier, opHash, userOp, userOpSignature); + ( + ValidationId vId, + function(ValidationId, bytes32, PackedUserOperation calldata, bytes calldata) internal returns(uint256) + validateUserOpFn, + bytes32 opHash, + bytes calldata userOpSignature + ) = _processUserOp(userOp, userOpHash); + validationData = validateUserOpFn(vId, opHash, userOp, userOpSignature); assembly { if missingAccountFunds { pop(call(gas(), caller(), missingAccountFunds, callvalue(), callvalue(), callvalue(), callvalue())) @@ -57,12 +64,20 @@ contract Kernel is ModuleManager, ExecutionManager, EIP712 { function _processUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash) internal - returns (ValidationId verifier, bytes32 opHash, bytes calldata signature) + returns ( + ValidationId vId, + function(ValidationId, bytes32, PackedUserOperation calldata, bytes calldata) internal returns(uint256) + validateUserOpFn, + bytes32 opHash, + bytes calldata signature + ) { /* userOp.nonce = vMode | vType | vId */ - (ValidationMode vMode, ValidationType vType, ValidationId vId) = parseNonce(userOp.nonce); + ValidationMode vMode; + ValidationType vType; + (vMode, vType, vId) = parseNonce(userOp.nonce); signature = userOp.signature; if (isEnable(vMode)) { bool enableReplayable = isEnableReplayable(vMode); @@ -70,11 +85,13 @@ contract Kernel is ModuleManager, ExecutionManager, EIP712 { assembly { sig := signature.offset } - _verifyInstallSignature(enableReplayable, sig.packages, sig.enableSignature); + require( + _verifyInstallSignature(enableReplayable, sig.packages, sig.enableSignature), InvalidEnableSignature() + ); _install(sig.packages); signature = sig.userOpSignature; } - verifier = _checkValidation(vMode, vType, vId); + (vId, validateUserOpFn) = _checkValidation(vMode, vType, vId); opHash = isReplayable(vMode) ? Lib4337.chainAgnosticUserOpHash(msg.sender, userOp) : userOpHash; } @@ -102,6 +119,19 @@ contract Kernel is ModuleManager, ExecutionManager, EIP712 { } function _fallback() internal returns (bytes memory res) { + /// @solidity memory-safe-assembly + assembly { + let s := shr(224, calldataload(0)) + // 0x150b7a02: `onERC721Received(address,address,uint256,bytes)`. + // 0xf23a6e61: `onERC1155Received(address,address,uint256,uint256,bytes)`. + // 0xbc197c81: `onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)`. + if or(eq(s, 0x150b7a02), or(eq(s, 0xf23a6e61), eq(s, 0xbc197c81))) { + // Assumes `mload(0x40) <= 0xffffffff` to save gas on cleaning lower bytes. + mstore(0x20, s) // Store `msg.sig`. + return(0x3c, 0x20) // Return `msg.sig`. + } + } + bytes4 selector = bytes4(msg.data[0:4]); SelectorConfig storage $ = _selectorConfig(selector); if ($.target == address(0)) { @@ -196,10 +226,14 @@ contract Kernel is ModuleManager, ExecutionManager, EIP712 { ) ) ); - _verifySignature(vId, address(this), digest, signature); + return _verifySignature(vId, address(this), digest, signature) == ERC1271_MAGICVALUE ? true : false; } fallback(bytes calldata) external payable returns (bytes memory) { return _fallback(); } + + receive() external payable { + emit Received(msg.sender, msg.value); + } } diff --git a/src/core/ModuleManager.sol b/src/core/ModuleManager.sol index 6a783d30..78d24c0e 100644 --- a/src/core/ModuleManager.sol +++ b/src/core/ModuleManager.sol @@ -93,9 +93,11 @@ contract ModuleManager is ValidationManager, ExecutorManager, HookManager, Selec } function _install(Install[] calldata packages) internal { - for (uint256 i = 0; i < packages.length; i++) { - Install calldata pkg = packages[i]; - _installModule(pkg.moduleType, pkg.module, pkg.moduleData, pkg.internalData); + unchecked { + for (uint256 i = 0; i < packages.length; i++) { + Install calldata pkg = packages[i]; + _installModule(pkg.moduleType, pkg.module, pkg.moduleData, pkg.internalData); + } } } diff --git a/src/core/ValidationManager.sol b/src/core/ValidationManager.sol index 566d6299..33eebb96 100644 --- a/src/core/ValidationManager.sol +++ b/src/core/ValidationManager.sol @@ -7,24 +7,8 @@ import "../types/Types.sol"; import "../types/Constants.sol"; import "../types/Structs.sol"; import {ECDSA} from "solady/utils/ECDSA.sol"; - -struct ValidationInfo { - ValidationType vType; - address[] policies; - address signer; - bytes4 group; -} - -struct ValidationGroupInfo { - mapping(bytes4 selector => bool) allowed; - bytes32 permission; -} - -struct ValidationStorage { - ValidationId root; - mapping(ValidationId vId => ValidationInfo) vInfo; - mapping(bytes4 group => ValidationGroupInfo) gInfo; -} +import "forge-std/console.sol"; +import {Lib4337} from "../lib/Lib4337.sol"; function getValidator(ValidationId vId) pure returns (address v) { assembly { @@ -52,6 +36,11 @@ function parseNonce(uint256 nonce) pure returns (ValidationMode vMode, Validatio abstract contract ValidationManager { ValidationId transient installingPermission; + function validationInfo(ValidationId vId) external view returns(ValidationInfo memory) { + ValidationStorage storage $ = _validationStorage(); + return $.vInfo[vId]; + } + function _validationStorage() internal view returns (ValidationStorage storage $) { assembly { $.slot := VALIDATION_MANAGER_STORAGE_SLOT @@ -61,72 +50,99 @@ abstract contract ValidationManager { function _installValidator(address _validator, bytes calldata _internalData, bool _installSuccess) internal { require(_installSuccess, ModuleInstallFailed()); ValidationStorage storage $ = _validationStorage(); - $.vInfo[ValidationId.wrap(bytes20(_validator))].vType = VALIDATION_TYPE_VALIDATOR; + ValidationId vId = ValidationId.wrap(bytes20(_validator)); + require($.vInfo[vId].vType == VALIDATION_TYPE_ROOT, OccupiedValidationId()); + $.vInfo[vId].vType = VALIDATION_TYPE_VALIDATOR; } - function _uninstallValidator(address _validator, bytes calldata _internalData, bool _uninstallSuccess) internal { - ValidationStorage storage $ = _validationStorage(); - $.vInfo[ValidationId.wrap(bytes20(_validator))].vType = VALIDATION_TYPE_ROOT; + function _installPolicy(address _policy, bytes calldata _internalData, bool _installSuccess) internal { + ValidationInfo storage $ = _checkPermissionInstall(_internalData, _installSuccess); + $.policies.push(_policy); } - function _installPolicy(address _policy, bytes calldata _internalData, bool _installSuccess) internal { + function _installSigner(address _signer, bytes calldata _internalData, bool _installSuccess) internal { + ValidationInfo storage $ = _checkPermissionInstall(_internalData, _installSuccess); + $.signer = _signer; + installingPermission = ValidationId.wrap(bytes20(0)); + } + + function _checkPermissionInstall(bytes calldata _internalData, bool _installSuccess) internal returns(ValidationInfo storage $) { require(_installSuccess, ModuleInstallFailed()); - ValidationStorage storage $ = _validationStorage(); ValidationId vId = ValidationId.wrap(bytes20(_internalData[0:20])); + $ = _validationStorage().vInfo[vId]; if (installingPermission == ValidationId.wrap(bytes20(0))) { require(vId != ValidationId.wrap(bytes20(0)), "invalid validationId"); - installingPermission = ValidationId.wrap(bytes20(_internalData[0:20])); - $.vInfo[vId].vType = VALIDATION_TYPE_PERMISSION; + require($.vType == ValidationType.wrap(0x00), "already taken"); + installingPermission = vId; + $.vType = VALIDATION_TYPE_PERMISSION; } else { require(installingPermission == vId, "permissionId should be consistent"); } - $.vInfo[vId].policies.push(_policy); } - function _uninstallPolicy(address _policy, bytes calldata _internalData, bool _uninstallSuccess) internal {} - - function _installSigner(address _signer, bytes calldata _internalData, bool _installSuccess) internal { - require(_installSuccess, ModuleInstallFailed()); + function _uninstallValidator(address _validator, bytes calldata _internalData, bool _uninstallSuccess) internal { ValidationStorage storage $ = _validationStorage(); - ValidationId vId = ValidationId.wrap(bytes20(_internalData[0:20])); - if (installingPermission == ValidationId.wrap(bytes20(0))) { - require(vId != ValidationId.wrap(bytes20(0)), "invalid validationId"); - require($.vInfo[vId].vType == ValidationType.wrap(0x00), "already taken"); - installingPermission = ValidationId.wrap(bytes20(_internalData[0:20])); - $.vInfo[vId].vType = VALIDATION_TYPE_PERMISSION; - } else { - require(installingPermission == vId, "permissionId should be consistent"); - } - $.vInfo[vId].signer = _signer; + ValidationId vId = ValidationId.wrap(bytes20(_validator)); + $.vInfo[vId].vType = VALIDATION_TYPE_ROOT; + } - installingPermission = ValidationId.wrap(bytes20(0)); + function _uninstallPolicy(address _policy, bytes calldata _internalData, bool _uninstallSuccess) internal { + ValidationId vId = ValidationId.wrap(bytes20(_internalData[0:20])); + ValidationInfo storage $ = _validationStorage().vInfo[vId]; + $ = _validationStorage().vInfo[vId]; + require($.policies[$.policies.length - 1] == _policy, InvalidPermissionUninstallOrder()); + $.policies.pop(); } - function _uninstallSigner(address _signer, bytes calldata _internalData, bool _uninstallSuccess) internal {} + function _uninstallSigner(address _signer, bytes calldata _internalData, bool _uninstallSuccess) internal { + ValidationId vId = ValidationId.wrap(bytes20(_internalData[0:20])); + ValidationInfo storage $ = _validationStorage().vInfo[vId]; + require($.policies.length == 0, InvalidPermissionUninstallOrder()); + require($.signer == _signer, InvalidPermissionId()); + $.signer = address(0); + $.vType = VALIDATION_TYPE_ROOT; + } - function _checkValidation(ValidationMode vMode, ValidationType vType, ValidationId vId) internal view returns(ValidationId v) { + function _checkValidation(ValidationMode vMode, ValidationType vType, ValidationId vId) + internal + view + returns ( + ValidationId v, + function(ValidationId, bytes32, PackedUserOperation calldata, bytes calldata) internal returns(uint256) + validateUserOp + ) + { ValidationStorage storage $ = _validationStorage(); - if (vType == VALIDATION_TYPE_ROOT) { + if (vType == VALIDATION_TYPE_ROOT || $.vInfo[vId].vType == VALIDATION_TYPE_ROOT) { v = $.root; + vType = $.vInfo[v].vType; } else { v = vId; require($.vInfo[vId].vType == vType, InvalidValidator()); } + + if (vType == VALIDATION_TYPE_VALIDATOR) { + validateUserOp = _validateUserOpValidator; + } else if (vType == VALIDATION_TYPE_PERMISSION) { + validateUserOp = _validateUserOpPermission; + } else { + revert InvalidValidationType(); + } } function _verifySignature(ValidationId vId, address requester, bytes32 _hash, bytes calldata _signature) internal view - returns (uint256 validationData) + returns (bytes4) { if (ValidationId.unwrap(vId) == bytes20(0)) { - return _verify7702Signature(_hash, _signature) ? 0 : 1; + return _verify7702Signature(_hash, _signature) ? ERC1271_MAGICVALUE : ERC1271_INVALID; } IValidator validator = IValidator(getValidator(vId)); // TODO: add permission support; - validator.isValidSignatureWithSender(requester, /*NOTE: fix this */ _hash, _signature); + return validator.isValidSignatureWithSender(requester, /*NOTE: fix this */ _hash, _signature); } - function _validateUserOp( + function _validateUserOpValidator( ValidationId vId, bytes32 opHash, PackedUserOperation calldata op, @@ -142,6 +158,37 @@ abstract contract ValidationManager { return IValidator(validator).validateUserOp(modifiedOp, opHash); } + struct PermissionSignature { + bytes[] signatures; + } + + function _validateUserOpPermission( + ValidationId vId, + bytes32 opHash, + PackedUserOperation calldata op, + bytes calldata userOpSignature + ) internal returns (uint256 validationData) { + ValidationInfo storage vInfo = _validationStorage().vInfo[vId]; + unchecked { + uint256 length = vInfo.policies.length + 1; + + PermissionSignature calldata permissionSig; + assembly { + permissionSig := userOpSignature.offset + } + PackedUserOperation memory modifiedOp = op; + bytes32 paddedVId = bytes32(ValidationId.unwrap(vId)); + for (uint256 i = 0; i < vInfo.policies.length; i++) { + IPolicy policy = IPolicy(vInfo.policies[i]); + modifiedOp.signature = permissionSig.signatures[i]; + validationData = _intersectValidationData(validationData, policy.checkUserOpPolicy(paddedVId, modifiedOp)); + } + + modifiedOp.signature = permissionSig.signatures[permissionSig.signatures.length - 1]; + return _intersectValidationData(validationData, ISigner(vInfo.signer).checkUserOpSignature(paddedVId, modifiedOp, opHash)); + } + } + function _verify7702Signature(bytes32 hash, bytes calldata sig) internal view returns (bool) { return ECDSA.recover(hash, sig) == address(this); } @@ -162,4 +209,37 @@ abstract contract ValidationManager { ValidationStorage storage $ = _validationStorage(); $.root = vId; } + + function _intersectValidationData(uint256 a, uint256 b) internal pure returns (uint256 validationData) { + assembly { + // xor(a,b) == shows only matching bits + // and(xor(a,b), 0x000000000000000000000000ffffffffffffffffffffffffffffffffffffffff) == filters out the validAfter and validUntil bits + // if the result is not zero, then aggregator part is not matching + // validCase : + // a == 0 || b == 0 || xor(a,b) == 0 + // invalidCase : + // a mul b != 0 && xor(a,b) != 0 + let sum := shl(96, add(a, b)) + switch or( + iszero(and(xor(a, b), 0x000000000000000000000000ffffffffffffffffffffffffffffffffffffffff)), + or(eq(sum, shl(96, a)), eq(sum, shl(96, b))) + ) + case 1 { + validationData := and(or(a, b), 0x000000000000000000000000ffffffffffffffffffffffffffffffffffffffff) + // validAfter + let a_vd := and(0xffffffffffff0000000000000000000000000000000000000000000000000000, a) + let b_vd := and(0xffffffffffff0000000000000000000000000000000000000000000000000000, b) + validationData := or(validationData, xor(a_vd, mul(xor(a_vd, b_vd), gt(b_vd, a_vd)))) + // validUntil + a_vd := and(0x000000000000ffffffffffff0000000000000000000000000000000000000000, a) + if iszero(a_vd) { a_vd := 0x000000000000ffffffffffff0000000000000000000000000000000000000000 } + b_vd := and(0x000000000000ffffffffffff0000000000000000000000000000000000000000, b) + if iszero(b_vd) { b_vd := 0x000000000000ffffffffffff0000000000000000000000000000000000000000 } + let until := xor(a_vd, mul(xor(a_vd, b_vd), lt(b_vd, a_vd))) + if iszero(until) { until := 0x000000000000ffffffffffff0000000000000000000000000000000000000000 } + validationData := or(validationData, until) + } + default { validationData := SIG_VALIDATION_FAILED_UINT } + } + } } diff --git a/src/lib/Lib4337.sol b/src/lib/Lib4337.sol index ff829cb6..f6ab120f 100644 --- a/src/lib/Lib4337.sol +++ b/src/lib/Lib4337.sol @@ -3,20 +3,22 @@ pragma solidity ^0.8.0; import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; import {UserOperationLib} from "account-abstraction/core/UserOperationLib.sol"; import {Eip7702Support} from "account-abstraction/core/Eip7702Support.sol"; +import {SIG_VALIDATION_FAILED_UINT} from "../types/Constants.sol"; +import {ValidationData} from "../types/Types.sol"; interface IERC5267 { function eip712Domain() - external - view - returns ( - bytes1 fields, - string memory name, - string memory version, - uint256 chainId, - address verifyingContract, - bytes32 salt, - uint256[] memory extensions - ); + external + view + returns ( + bytes1 fields, + string memory name, + string memory version, + uint256 chainId, + address verifyingContract, + bytes32 salt, + uint256[] memory extensions + ); } library Lib4337 { @@ -48,4 +50,37 @@ library Lib4337 { mstore(0x60, 0) // Restore the zero pointer. } } + + function _intersectValidationData(ValidationData a, ValidationData b) internal pure returns (ValidationData validationData) { + assembly { + // xor(a,b) == shows only matching bits + // and(xor(a,b), 0x000000000000000000000000ffffffffffffffffffffffffffffffffffffffff) == filters out the validAfter and validUntil bits + // if the result is not zero, then aggregator part is not matching + // validCase : + // a == 0 || b == 0 || xor(a,b) == 0 + // invalidCase : + // a mul b != 0 && xor(a,b) != 0 + let sum := shl(96, add(a, b)) + switch or( + iszero(and(xor(a, b), 0x000000000000000000000000ffffffffffffffffffffffffffffffffffffffff)), + or(eq(sum, shl(96, a)), eq(sum, shl(96, b))) + ) + case 1 { + validationData := and(or(a, b), 0x000000000000000000000000ffffffffffffffffffffffffffffffffffffffff) + // validAfter + let a_vd := and(0xffffffffffff0000000000000000000000000000000000000000000000000000, a) + let b_vd := and(0xffffffffffff0000000000000000000000000000000000000000000000000000, b) + validationData := or(validationData, xor(a_vd, mul(xor(a_vd, b_vd), gt(b_vd, a_vd)))) + // validUntil + a_vd := and(0x000000000000ffffffffffff0000000000000000000000000000000000000000, a) + if iszero(a_vd) { a_vd := 0x000000000000ffffffffffff0000000000000000000000000000000000000000 } + b_vd := and(0x000000000000ffffffffffff0000000000000000000000000000000000000000, b) + if iszero(b_vd) { b_vd := 0x000000000000ffffffffffff0000000000000000000000000000000000000000 } + let until := xor(a_vd, mul(xor(a_vd, b_vd), lt(b_vd, a_vd))) + if iszero(until) { until := 0x000000000000ffffffffffff0000000000000000000000000000000000000000 } + validationData := or(validationData, until) + } + default { validationData := SIG_VALIDATION_FAILED_UINT } + } + } } diff --git a/src/types/Constants.sol b/src/types/Constants.sol index 64977f48..9eff24e9 100644 --- a/src/types/Constants.sol +++ b/src/types/Constants.sol @@ -31,3 +31,8 @@ bytes32 constant HOOK_MANAGER_STORAGE_SLOT = 0x4605d5f70bb605094b2e761eccdc27bed // bytes32(uint256(keccak256('kernel.v3.validation')) - 1) bytes32 constant VALIDATION_MANAGER_STORAGE_SLOT = 0x7bcaa2ced2a71450ed5a9a1b4848e8e5206dbc3f06011e595f7f55428cc6f84f; bytes32 constant ERC1967_IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; +bytes4 constant ERC1271_MAGICVALUE = 0x1626ba7e; +bytes4 constant ERC1271_INVALID = 0xffffffff; +ValidationData constant SIG_VALIDATION_FAILED = ValidationData.wrap(SIG_VALIDATION_FAILED_UINT); +uint256 constant SIG_VALIDATION_FAILED_UINT = 1; +uint256 constant SIG_VALIDATION_SUCCESS_UINT = 0; diff --git a/src/types/Error.sol b/src/types/Error.sol index abe5a638..eb80e8a8 100644 --- a/src/types/Error.sol +++ b/src/types/Error.sol @@ -16,3 +16,12 @@ error InvalidCallType(); error InvalidExecType(); error InvalidSelector(); +error InvalidEnableSignature(); + +error Unauthorized(); + +error InvalidValidationType(); +error OccupiedValidationId(); + +error InvalidPermissionUninstallOrder(); +error InvalidPermissionId(); diff --git a/src/types/Events.sol b/src/types/Events.sol index 10710bd6..2e57fe87 100644 --- a/src/types/Events.sol +++ b/src/types/Events.sol @@ -3,3 +3,5 @@ pragma solidity ^0.8.0; event ModuleInstalled(uint256 moduleType, address module); event ModuleUninstalled(uint256 moduleType, address module); + +event Received(address sender, uint256 amount); diff --git a/src/types/Structs.sol b/src/types/Structs.sol index 54b3f85a..443b7045 100644 --- a/src/types/Structs.sol +++ b/src/types/Structs.sol @@ -1,3 +1,7 @@ +pragma solidity ^0.8.0; + +import "./Types.sol"; + struct Install { uint256 moduleType; address module; @@ -10,3 +14,14 @@ struct Uninstall { address module; bytes data; } + +struct ValidationInfo { + ValidationType vType; + address[] policies; + address signer; +} + +struct ValidationStorage { + ValidationId root; + mapping(ValidationId vId => ValidationInfo) vInfo; +} diff --git a/src/types/Types.sol b/src/types/Types.sol index 1bd763d3..8594fa88 100644 --- a/src/types/Types.sol +++ b/src/types/Types.sol @@ -23,6 +23,35 @@ type ExecModeSelector is bytes4; type ExecModePayload is bytes22; +type ValidationData is uint256; + +type ValidAfter is uint48; + +type ValidUntil is uint48; + +function getValidationResult(ValidationData validationData) pure returns (address result) { + assembly { + result := validationData + } +} + +function packValidationData(ValidAfter validAfter, ValidUntil validUntil) pure returns (uint256) { + return uint256(ValidAfter.unwrap(validAfter)) << 208 | uint256(ValidUntil.unwrap(validUntil)) << 160; +} + +function parseValidationData(uint256 validationData) + pure + returns (ValidAfter validAfter, ValidUntil validUntil, address result) +{ + assembly { + result := validationData + validUntil := and(shr(160, validationData), 0xffffffffffff) + switch iszero(validUntil) + case 1 { validUntil := 0xffffffffffff } + validAfter := shr(208, validationData) + } +} + using {vTypeEqual as ==} for ValidationType global; using {eqCallType as ==} for CallType global; using {notEqCallType as !=} for CallType global; @@ -51,18 +80,18 @@ function vTypeEqual(ValidationType a, ValidationType b) pure returns (bool) { function isEnable(ValidationMode vMode) pure returns (bool enable) { assembly { - enable := iszero(iszero(and(vMode, 8))) + enable := iszero(iszero(and(vMode, 0x800000000000000000000000000000000000000000000000000000000000000))) } } function isReplayable(ValidationMode vMode) pure returns (bool replayable) { assembly { - replayable := iszero(iszero(and(vMode, 64))) + replayable := iszero(iszero(and(vMode, 0x4000000000000000000000000000000000000000000000000000000000000000))) } } function isEnableReplayable(ValidationMode vMode) pure returns (bool replayable) { assembly { - replayable := iszero(iszero(and(vMode, 4))) + replayable := iszero(iszero(and(vMode, 0x400000000000000000000000000000000000000000000000000000000000000))) } } diff --git a/test/Kernel.t.sol b/test/Kernel.t.sol index 1911d500..e0e67e37 100644 --- a/test/Kernel.t.sol +++ b/test/Kernel.t.sol @@ -13,9 +13,17 @@ import {MockFallback} from "./mock/MockFallback.sol"; import {MockExecutor} from "./mock/MockExecutor.sol"; import {MockValidator} from "./mock/MockValidator.sol"; import {MockHook} from "./mock/MockHook.sol"; +import {MockPolicy} from "./mock/MockPolicy.sol"; +import {MockSigner} from "./mock/MockSigner.sol"; +import {MockERC721} from "./mock/MockERC721.sol"; +import {MockERC1155} from "./mock/MockERC1155.sol"; import {IHook} from "src/interfaces/IERC7579Modules.sol"; import {CallType} from "src/types/Types.sol"; +import "src/types/Constants.sol"; +import "forge-std/console.sol"; import "src/types/Error.sol"; +import "src/types/Events.sol"; +import "src/types/Structs.sol"; contract MockCallee { uint256 public bar; @@ -45,6 +53,16 @@ struct Call { bytes data; } +contract MockContractETH { + function useTransfer(address payable recipient, uint256 v) external { + recipient.transfer(v); + } + + function useSend(address payable recipient, uint256 v) external { + require(recipient.send(v), "send failed"); + } +} + contract KernelTest is Test { IEntryPoint ep; KernelFactory factory; @@ -93,28 +111,308 @@ contract KernelTest is Test { vm.stopPrank(); } - function encodeNonce(bool replayableUserOp, bool enableFlag, bool replayableEnable, bytes1 vType, bytes20 vId) internal returns(uint256 nonce) { + function encodeNonce(bool replayableUserOp, bool enableFlag, bool replayableEnable, bytes1 vType, bytes20 vId) + internal + returns (uint256 nonce) + { uint8 uMode = 0; - if(replayableEnable) { - uMode += 2**6; + if (replayableEnable) { + uMode += 2 ** 6; } - if(enableFlag) { - uMode += 2**3; + if (enableFlag) { + uMode += 2 ** 3; } - if(replayableEnable) { - uMode += 2**2; + if (replayableEnable) { + uMode += 2 ** 2; } uint192 key = uint192(bytes24(abi.encodePacked(uMode, vType, vId, bytes2(0x00)))); return ep.getNonce(address(kernel), key); } - function test_userop() external entryPointTest { + function test_codesize() external { + address implementation = address(factory.template()); + require(implementation.code.length <= 24576, "Code too big"); + console.log("Code size :", implementation.code.length); + } + + function test_receive_eth() external { + address sender = makeAddr("Sender"); + address payable k = payable(address(kernel)); + vm.deal(sender, 1e18); + // if not through kernel, only
call{value} works + vm.startPrank(sender); + vm.expectEmit(k); + emit Received(sender, uint256(1)); + (bool success, ) = k.call{value: 1}(hex""); + require(success); + vm.stopPrank(); + + MockContractETH mock = new MockContractETH(); + vm.deal(address(mock), 1e18); + // if done through kernel, accepts both transfer and send + vm.startPrank(address(ep)); + vm.expectEmit(k); + emit Received(address(mock), uint256(1)); + kernel.execute(bytes32(0), abi.encodePacked(address(mock), uint256(0), abi.encodeWithSelector(MockContractETH.useTransfer.selector, k, uint256(1)))); + vm.expectEmit(k); + emit Received(address(mock), uint256(1)); + kernel.execute(bytes32(0), abi.encodePacked(address(mock), uint256(0), abi.encodeWithSelector(MockContractETH.useSend.selector, k, uint256(1)))); + vm.stopPrank(); + } + + function test_receive_erc721() external { + MockERC721 mock = new MockERC721(); + address sender = makeAddr("Sender"); + + mock.mint(sender, 1); + + vm.prank(sender); + mock.safeTransferFrom(sender, address(kernel), 1); + + mock.safeMint(address(kernel), 2); + } + + function test_receive_erc1155() external { + MockERC1155 mock = new MockERC1155(); + address sender = makeAddr("Sender"); + + mock.mint(sender, 1, 1, hex"deadbeef"); + vm.prank(sender); + mock.safeTransferFrom(sender, address(kernel), 1, 1, hex"deadbeef"); + + mock.mint(address(kernel), 1, 1, hex"deadbeef"); + + mock.mint(sender, 2, 4, hex"deadbeef"); + mock.mint(sender, 3, 5, hex"deadbeef"); + uint256[] memory ids = new uint256[](2); + ids[0] = 2; + ids[1] = 3; + + uint256[] memory amounts = new uint256[](2); + amounts[0] = 2; + amounts[1] = 3; + vm.prank(sender); + mock.safeBatchTransferFrom(sender, address(kernel), ids, amounts, hex"deadbeef"); + + mock.batchMint(address(kernel), ids, amounts, hex"deadbeef"); + } + + function test_userop_root() external entryPointTest { + PackedUserOperation[] memory ops = new PackedUserOperation[](1); + ops[0] = PackedUserOperation({ + sender: address(kernel), + nonce: encodeNonce(false, false, false, bytes1(0), bytes20(0)), + initCode: hex"", + callData: abi.encodeWithSelector( + Kernel.execute.selector, bytes32(0), abi.encodePacked(address(callee), uint256(0), MockCallee.foo.selector) + ), + accountGasLimits: bytes32(abi.encodePacked(uint128(1000000), uint128(1000000))), // TODO make this dynamic + preVerificationGas: 1000000, + gasFees: bytes32(abi.encodePacked(uint128(1), uint128(1))), + paymasterAndData: hex"", + signature: hex"" + }); + mockValidator.sudoSetSuccess(true); + ep.handleOps(ops, beneficiary); + assertEq(callee.bar(), 1); + } + + function test_userop_root_aa24_validation_failed() external entryPointTest { + PackedUserOperation[] memory ops = new PackedUserOperation[](1); + ops[0] = PackedUserOperation({ + sender: address(kernel), + nonce: encodeNonce(false, false, false, bytes1(0x00), bytes20(0)), + initCode: hex"", + callData: abi.encodeWithSelector( + Kernel.execute.selector, bytes32(0), abi.encodePacked(address(callee), uint256(0), MockCallee.foo.selector) + ), + accountGasLimits: bytes32(abi.encodePacked(uint128(1000000), uint128(1000000))), // TODO make this dynamic + preVerificationGas: 1000000, + gasFees: bytes32(abi.encodePacked(uint128(1), uint128(1))), + paymasterAndData: hex"", + signature: hex"" + }); + mockValidator.sudoSetSuccess(false); + vm.expectRevert(abi.encodeWithSelector(IEntryPoint.FailedOp.selector, 0, "AA24 signature error")); + ep.handleOps(ops, beneficiary); + } + + function test_userop_validator_aa24_notinstalled() external entryPointTest { + MockValidator newValidator = new MockValidator(); + PackedUserOperation[] memory ops = new PackedUserOperation[](1); + ops[0] = PackedUserOperation({ + sender: address(kernel), + nonce: encodeNonce(false, false, false, bytes1(0x01), bytes20(address(newValidator))), + initCode: hex"", + callData: abi.encodeWithSelector( + Kernel.execute.selector, bytes32(0), abi.encodePacked(address(callee), uint256(0), MockCallee.foo.selector) + ), + accountGasLimits: bytes32(abi.encodePacked(uint128(1000000), uint128(1000000))), // TODO make this dynamic + preVerificationGas: 1000000, + gasFees: bytes32(abi.encodePacked(uint128(1), uint128(1))), + paymasterAndData: hex"", + signature: hex"" + }); + mockValidator.sudoSetSuccess(false); + newValidator.sudoSetSuccess(true); + vm.expectRevert(abi.encodeWithSelector(IEntryPoint.FailedOp.selector, 0, "AA24 signature error")); + ep.handleOps(ops, beneficiary); + } + + function test_userop_validator_use_root_if_notinstalled() external entryPointTest { + MockValidator newValidator = new MockValidator(); + PackedUserOperation[] memory ops = new PackedUserOperation[](1); + ops[0] = PackedUserOperation({ + sender: address(kernel), + nonce: encodeNonce(false, false, false, bytes1(0x01), bytes20(address(newValidator))), + initCode: hex"", + callData: abi.encodeWithSelector( + Kernel.execute.selector, bytes32(0), abi.encodePacked(address(callee), uint256(0), MockCallee.foo.selector) + ), + accountGasLimits: bytes32(abi.encodePacked(uint128(1000000), uint128(1000000))), // TODO make this dynamic + preVerificationGas: 1000000, + gasFees: bytes32(abi.encodePacked(uint128(1), uint128(1))), + paymasterAndData: hex"", + signature: hex"" + }); + mockValidator.sudoSetSuccess(true); + newValidator.sudoSetSuccess(false); + ep.handleOps(ops, beneficiary); + assertEq(callee.bar(), 1); + } + + function test_userop_validator_enable() external entryPointTest { + MockValidator newValidator = new MockValidator(); + PackedUserOperation[] memory ops = new PackedUserOperation[](1); + ops[0] = PackedUserOperation({ + sender: address(kernel), + nonce: encodeNonce(false, true, false, bytes1(0x01), bytes20(address(newValidator))), + initCode: hex"", + callData: abi.encodeWithSelector( + Kernel.execute.selector, bytes32(0), abi.encodePacked(address(callee), uint256(0), MockCallee.foo.selector) + ), + accountGasLimits: bytes32(abi.encodePacked(uint128(1000000), uint128(1000000))), // TODO make this dynamic + preVerificationGas: 1000000, + gasFees: bytes32(abi.encodePacked(uint128(1), uint128(1))), + paymasterAndData: hex"", + signature: hex"" + }); + + Install[] memory packages = new Install[](1); + packages[0] = Install({moduleType: 1, module: address(newValidator), moduleData: hex"", internalData: hex""}); + + bytes memory sig = abi.encode(packages, hex"", hex""); + + ops[0].signature = sig; + mockValidator.sudoSetSuccess(false); + mockValidator.sudoSetValidSig(hex""); + newValidator.sudoSetSuccess(true); + ep.handleOps(ops, beneficiary); + assertEq(callee.bar(), 1); + } + + function test_userop_validator_aa23_enable_fail_wrong_signature() external entryPointTest { + MockValidator newValidator = new MockValidator(); + PackedUserOperation[] memory ops = new PackedUserOperation[](1); + ops[0] = PackedUserOperation({ + sender: address(kernel), + nonce: encodeNonce(false, true, false, bytes1(0x01), bytes20(address(newValidator))), + initCode: hex"", + callData: abi.encodeWithSelector( + Kernel.execute.selector, bytes32(0), abi.encodePacked(address(callee), uint256(0), MockCallee.foo.selector) + ), + accountGasLimits: bytes32(abi.encodePacked(uint128(1000000), uint128(1000000))), // TODO make this dynamic + preVerificationGas: 1000000, + gasFees: bytes32(abi.encodePacked(uint128(1), uint128(1))), + paymasterAndData: hex"", + signature: hex"" + }); + + Install[] memory packages = new Install[](1); + packages[0] = Install({moduleType: 1, module: address(newValidator), moduleData: hex"", internalData: hex""}); + + bytes memory sig = abi.encode(packages, hex"", hex""); + + ops[0].signature = sig; + mockValidator.sudoSetSuccess(false); + newValidator.sudoSetSuccess(true); + newValidator.sudoSetValidSig(hex""); + vm.expectRevert( + abi.encodeWithSelector( + IEntryPoint.FailedOpWithRevert.selector, + 0, + "AA23 reverted", + abi.encodeWithSelector(InvalidEnableSignature.selector) + ) + ); + ep.handleOps(ops, beneficiary); + } + + function test_userop_validator_aa24_validation_failed() external entryPointTest { + MockValidator newValidator = new MockValidator(); + PackedUserOperation[] memory ops = new PackedUserOperation[](1); + ops[0] = PackedUserOperation({ + sender: address(kernel), + nonce: encodeNonce(false, true, false, bytes1(0x01), bytes20(address(newValidator))), + initCode: hex"", + callData: abi.encodeWithSelector( + Kernel.execute.selector, bytes32(0), abi.encodePacked(address(callee), uint256(0), MockCallee.foo.selector) + ), + accountGasLimits: bytes32(abi.encodePacked(uint128(1000000), uint128(1000000))), // TODO make this dynamic + preVerificationGas: 1000000, + gasFees: bytes32(abi.encodePacked(uint128(1), uint128(1))), + paymasterAndData: hex"", + signature: hex"" + }); + + Install[] memory packages = new Install[](1); + packages[0] = Install({moduleType: 1, module: address(newValidator), moduleData: hex"", internalData: hex""}); + + bytes memory sig = abi.encode(packages, hex"", hex""); + + ops[0].signature = sig; + mockValidator.sudoSetSuccess(false); + newValidator.sudoSetSuccess(false); + mockValidator.sudoSetValidSig(hex""); + vm.expectRevert(abi.encodeWithSelector(IEntryPoint.FailedOp.selector, 0, "AA24 signature error")); + ep.handleOps(ops, beneficiary); + } + + function test_userop_permission_aa24_notinstalled() external entryPointTest { + MockPolicy policy = new MockPolicy(); + MockSigner signer = new MockSigner(); + bytes20 permissionId = bytes20(keccak256(abi.encodePacked("Hello world"))); + PackedUserOperation[] memory ops = new PackedUserOperation[](1); + ops[0] = PackedUserOperation({ + sender: address(kernel), + nonce: encodeNonce(false, false, false, bytes1(0x02), permissionId), + initCode: hex"", + callData: abi.encodeWithSelector( + Kernel.execute.selector, bytes32(0), abi.encodePacked(address(callee), uint256(0), MockCallee.foo.selector) + ), + accountGasLimits: bytes32(abi.encodePacked(uint128(1000000), uint128(1000000))), // TODO make this dynamic + preVerificationGas: 1000000, + gasFees: bytes32(abi.encodePacked(uint128(1), uint128(1))), + paymasterAndData: hex"", + signature: hex"" + }); + mockValidator.sudoSetSuccess(false); + vm.expectRevert(abi.encodeWithSelector(IEntryPoint.FailedOp.selector, 0, "AA24 signature error")); + ep.handleOps(ops, beneficiary); + } + + function test_userop_permission_use_root_if_notinstalled() external entryPointTest { + MockPolicy policy = new MockPolicy(); + MockSigner signer = new MockSigner(); + bytes20 permissionId = bytes20(keccak256(abi.encodePacked("Hello world"))); PackedUserOperation[] memory ops = new PackedUserOperation[](1); ops[0] = PackedUserOperation({ sender: address(kernel), - nonce : encodeNonce(false, false, false, bytes1(0), bytes20(0)), - initCode : hex"", - callData : abi.encodeWithSelector(Kernel.execute.selector, bytes32(0), abi.encodePacked(address(callee), MockCallee.foo.selector)), + nonce: encodeNonce(false, false, false, bytes1(0x02), permissionId), + initCode: hex"", + callData: abi.encodeWithSelector( + Kernel.execute.selector, bytes32(0), abi.encodePacked(address(callee), uint256(0), MockCallee.foo.selector) + ), accountGasLimits: bytes32(abi.encodePacked(uint128(1000000), uint128(1000000))), // TODO make this dynamic preVerificationGas: 1000000, gasFees: bytes32(abi.encodePacked(uint128(1), uint128(1))), @@ -123,6 +421,206 @@ contract KernelTest is Test { }); mockValidator.sudoSetSuccess(true); ep.handleOps(ops, beneficiary); + assertEq(callee.bar(), 1); + } + + function test_userop_permission_enable() external entryPointTest { + MockPolicy policy = new MockPolicy(); + MockSigner signer = new MockSigner(); + bytes20 permissionId = bytes20(keccak256(abi.encodePacked("Hello world"))); + PackedUserOperation[] memory ops = new PackedUserOperation[](1); + ops[0] = PackedUserOperation({ + sender: address(kernel), + nonce: encodeNonce(false, true, false, bytes1(0x02), permissionId), + initCode: hex"", + callData: abi.encodeWithSelector( + Kernel.execute.selector, bytes32(0), abi.encodePacked(address(callee), uint256(0), MockCallee.foo.selector) + ), + accountGasLimits: bytes32(abi.encodePacked(uint128(1000000), uint128(1000000))), // TODO make this dynamic + preVerificationGas: 1000000, + gasFees: bytes32(abi.encodePacked(uint128(1), uint128(1))), + paymasterAndData: hex"", + signature: hex"" + }); + + Install[] memory packages = new Install[](2); + packages[0] = Install({ + moduleType: 5, + module: address(policy), + moduleData: hex"", + internalData: abi.encodePacked(permissionId) + }); + packages[1] = Install({ + moduleType: 6, + module: address(signer), + moduleData: hex"", + internalData: abi.encodePacked(permissionId) + }); + + bytes[] memory signatures = new bytes[](2); + signatures[0] = hex""; + signatures[1] = hex""; + + bytes memory sig = abi.encode(packages, hex"", abi.encode(signatures)); + + ops[0].signature = sig; + mockValidator.sudoSetSuccess(false); + mockValidator.sudoSetValidSig(hex""); + + policy.sudoSetValidSig(address(kernel), bytes32(abi.encodePacked(permissionId)), hex""); + signer.sudoSetValidSig(address(kernel), bytes32(abi.encodePacked(permissionId)), hex""); + ep.handleOps(ops, beneficiary); + assertEq(callee.bar(), 1); + } + + function test_userop_permission_aa23_enable_fail_wrong_signature() external entryPointTest { + MockPolicy policy = new MockPolicy(); + MockSigner signer = new MockSigner(); + bytes20 permissionId = bytes20(keccak256(abi.encodePacked("Hello world"))); + PackedUserOperation[] memory ops = new PackedUserOperation[](1); + ops[0] = PackedUserOperation({ + sender: address(kernel), + nonce: encodeNonce(false, true, false, bytes1(0x02), permissionId), + initCode: hex"", + callData: abi.encodeWithSelector( + Kernel.execute.selector, bytes32(0), abi.encodePacked(address(callee), uint256(0), MockCallee.foo.selector) + ), + accountGasLimits: bytes32(abi.encodePacked(uint128(1000000), uint128(1000000))), // TODO make this dynamic + preVerificationGas: 1000000, + gasFees: bytes32(abi.encodePacked(uint128(1), uint128(1))), + paymasterAndData: hex"", + signature: hex"" + }); + + Install[] memory packages = new Install[](2); + packages[0] = Install({ + moduleType: 5, + module: address(policy), + moduleData: hex"", + internalData: abi.encodePacked(permissionId) + }); + packages[1] = Install({ + moduleType: 6, + module: address(signer), + moduleData: hex"", + internalData: abi.encodePacked(permissionId) + }); + + bytes[] memory signatures = new bytes[](2); + signatures[0] = hex""; + signatures[1] = hex""; + + bytes memory sig = abi.encode(packages, hex"", abi.encode(signatures)); + + ops[0].signature = sig; + mockValidator.sudoSetSuccess(false); + policy.sudoSetValidSig(address(kernel), bytes32(abi.encodePacked(permissionId)), hex""); + signer.sudoSetValidSig(address(kernel), bytes32(abi.encodePacked(permissionId)), hex""); + vm.expectRevert( + abi.encodeWithSelector( + IEntryPoint.FailedOpWithRevert.selector, + 0, + "AA23 reverted", + abi.encodeWithSelector(InvalidEnableSignature.selector) + ) + ); + ep.handleOps(ops, beneficiary); + } + + function test_userop_permission_aa23_policy_failed() external entryPointTest { + MockPolicy policy = new MockPolicy(); + MockSigner signer = new MockSigner(); + bytes20 permissionId = bytes20(keccak256(abi.encodePacked("Hello world"))); + PackedUserOperation[] memory ops = new PackedUserOperation[](1); + ops[0] = PackedUserOperation({ + sender: address(kernel), + nonce: encodeNonce(false, true, false, bytes1(0x02), permissionId), + initCode: hex"", + callData: abi.encodeWithSelector( + Kernel.execute.selector, bytes32(0), abi.encodePacked(address(callee), uint256(0), MockCallee.foo.selector) + ), + accountGasLimits: bytes32(abi.encodePacked(uint128(1000000), uint128(1000000))), // TODO make this dynamic + preVerificationGas: 1000000, + gasFees: bytes32(abi.encodePacked(uint128(1), uint128(1))), + paymasterAndData: hex"", + signature: hex"" + }); + + Install[] memory packages = new Install[](2); + packages[0] = Install({ + moduleType: 5, + module: address(policy), + moduleData: hex"", + internalData: abi.encodePacked(permissionId) + }); + packages[1] = Install({ + moduleType: 6, + module: address(signer), + moduleData: hex"", + internalData: abi.encodePacked(permissionId) + }); + + bytes[] memory signatures = new bytes[](2); + signatures[0] = hex""; + signatures[1] = hex""; + + bytes memory sig = abi.encode(packages, hex"", abi.encode(signatures)); + + ops[0].signature = sig; + mockValidator.sudoSetSuccess(false); + mockValidator.sudoSetValidSig(hex""); + policy.sudoSetValidSig(address(kernel), bytes32(abi.encodePacked(permissionId)), hex"deadbeef"); + signer.sudoSetValidSig(address(kernel), bytes32(abi.encodePacked(permissionId)), hex""); + vm.expectRevert(abi.encodeWithSelector(IEntryPoint.FailedOp.selector, 0, "AA24 signature error")); + ep.handleOps(ops, beneficiary); + } + + function test_userop_permission_aa24_signer_validation_failed() external entryPointTest { + MockPolicy policy = new MockPolicy(); + MockSigner signer = new MockSigner(); + bytes20 permissionId = bytes20(keccak256(abi.encodePacked("Hello world"))); + PackedUserOperation[] memory ops = new PackedUserOperation[](1); + ops[0] = PackedUserOperation({ + sender: address(kernel), + nonce: encodeNonce(false, true, false, bytes1(0x02), permissionId), + initCode: hex"", + callData: abi.encodeWithSelector( + Kernel.execute.selector, bytes32(0), abi.encodePacked(address(callee), uint256(0), MockCallee.foo.selector) + ), + accountGasLimits: bytes32(abi.encodePacked(uint128(1000000), uint128(1000000))), // TODO make this dynamic + preVerificationGas: 1000000, + gasFees: bytes32(abi.encodePacked(uint128(1), uint128(1))), + paymasterAndData: hex"", + signature: hex"" + }); + + Install[] memory packages = new Install[](2); + packages[0] = Install({ + moduleType: 5, + module: address(policy), + moduleData: hex"", + internalData: abi.encodePacked(permissionId) + }); + packages[1] = Install({ + moduleType: 6, + module: address(signer), + moduleData: hex"", + internalData: abi.encodePacked(permissionId) + }); + + bytes[] memory signatures = new bytes[](2); + signatures[0] = hex""; + signatures[1] = hex""; + + bytes memory sig = abi.encode(packages, hex"", abi.encode(signatures)); + + ops[0].signature = sig; + mockValidator.sudoSetSuccess(false); + mockValidator.sudoSetValidSig(hex""); + policy.sudoSetValidSig(address(kernel), bytes32(abi.encodePacked(permissionId)), hex""); + signer.sudoSetValidSig(address(kernel), bytes32(abi.encodePacked(permissionId)), hex"deadbeef"); + vm.expectRevert(abi.encodeWithSelector(IEntryPoint.FailedOp.selector, 0, "AA24 signature error")); + ep.handleOps(ops, beneficiary); } function test_deploy() external unitTest { @@ -171,7 +669,22 @@ contract KernelTest is Test { } function test_install_validator() external unitTest { - kernel.installModule(1, address(mockValidator), abi.encode(hex"deadbeef", "InternalData")); + MockValidator newValidator = new MockValidator(); + ValidationId vId = ValidationId.wrap(bytes20(address(newValidator))); + kernel.installModule(1, address(newValidator), abi.encode(hex"deadbeef", "InternalData")); + ValidationInfo memory vInfo = kernel.validationInfo(vId); + assertTrue(vInfo.vType == VALIDATION_TYPE_VALIDATOR); + } + + function test_uninstall_validator() external unitTest { + MockValidator newValidator = new MockValidator(); + ValidationId vId = ValidationId.wrap(bytes20(address(newValidator))); + kernel.installModule(1, address(newValidator), abi.encode(hex"deadbeef", "InternalData")); + ValidationInfo memory vInfo = kernel.validationInfo(vId); + assertTrue(vInfo.vType == VALIDATION_TYPE_VALIDATOR); + kernel.uninstallModule(1, address(newValidator), abi.encode(hex"deadbeef", "InternalData")); + vInfo = kernel.validationInfo(vId); + assertTrue(vInfo.vType == VALIDATION_TYPE_ROOT); } function test_install_selector_call() external unitTest { From 3023d7e3be77a84ce18b59732d23911338c4d20f Mon Sep 17 00:00:00 2001 From: leekt Date: Wed, 28 May 2025 01:00:28 +0900 Subject: [PATCH 016/121] preparing execute with signature --- src/Kernel.sol | 116 ++++------ src/KernelFactory.sol | 34 +-- src/KernelHelper.sol | 90 ++++++++ src/core/ModuleManager.sol | 64 +++++- src/core/ValidationManager.sol | 138 ++++++------ src/interfaces/IERC5267.sol | 16 ++ src/lib/Lib4337.sol | 56 +++-- src/lib/Utils.sol | 10 + src/types/Constants.sol | 1 + src/types/Types.sol | 13 -- test/Kernel.t.sol | 384 +++++++++++++++++---------------- 11 files changed, 536 insertions(+), 386 deletions(-) create mode 100644 src/KernelHelper.sol create mode 100644 src/interfaces/IERC5267.sol create mode 100644 src/lib/Utils.sol diff --git a/src/Kernel.sol b/src/Kernel.sol index bae6f982..0015302d 100644 --- a/src/Kernel.sol +++ b/src/Kernel.sol @@ -7,8 +7,8 @@ import {IValidator} from "./interfaces/IERC7579Modules.sol"; import {ModuleManager, Install} from "./core/ModuleManager.sol"; import {parseNonce} from "./core/ValidationManager.sol"; import {ExecutionManager} from "./core/ExecutionManager.sol"; -import {EIP712} from "solady/utils/EIP712.sol"; import {Lib4337} from "./lib/Lib4337.sol"; +import {UUPSUpgradeable} from "solady/utils/UUPSUpgradeable.sol"; import "./types/Types.sol"; import "./types/Error.sol"; import "./types/Events.sol"; @@ -16,18 +16,21 @@ import "./types/Constants.sol"; import "forge-std/console.sol"; -contract Kernel is ModuleManager, ExecutionManager, EIP712 { +contract Kernel is ModuleManager, ExecutionManager, UUPSUpgradeable { IEntryPoint immutable entryPoint; - modifier onlyEntryPointOrSelf() { + function _onlyEntryPointOrSelf() internal { require(msg.sender == address(entryPoint) || msg.sender == address(this), Unauthorized()); - _; } constructor(IEntryPoint _entryPoint) { entryPoint = _entryPoint; } + function _authorizeUpgrade(address) internal override { + _onlyEntryPointOrSelf(); + } + function _domainNameAndVersion() internal pure override returns (string memory name, string memory version) { name = "Kernel"; version = "0.4.0"; @@ -35,6 +38,7 @@ contract Kernel is ModuleManager, ExecutionManager, EIP712 { /// authentication struct EnableModeSignature { + uint256 nonce; Install[] packages; bytes enableSignature; bytes userOpSignature; @@ -43,78 +47,72 @@ contract Kernel is ModuleManager, ExecutionManager, EIP712 { function validateUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash, uint256 missingAccountFunds) external payable - onlyEntryPointOrSelf - returns (uint256 validationData) + returns (uint256) { - ( - ValidationId vId, - function(ValidationId, bytes32, PackedUserOperation calldata, bytes calldata) internal returns(uint256) - validateUserOpFn, - bytes32 opHash, - bytes calldata userOpSignature - ) = _processUserOp(userOp, userOpHash); - validationData = validateUserOpFn(vId, opHash, userOp, userOpSignature); + _onlyEntryPointOrSelf(); + uint256 validationData = _processUserOp(userOp, userOpHash); assembly { if missingAccountFunds { pop(call(gas(), caller(), missingAccountFunds, callvalue(), callvalue(), callvalue(), callvalue())) //ignore failure (its EntryPoint's job to verify, not account.) } } + return validationData; } function _processUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash) internal - returns ( - ValidationId vId, - function(ValidationId, bytes32, PackedUserOperation calldata, bytes calldata) internal returns(uint256) - validateUserOpFn, - bytes32 opHash, - bytes calldata signature - ) + returns (uint256 validationData) { /* userOp.nonce = vMode | vType | vId */ ValidationMode vMode; ValidationType vType; + ValidationId vId; + function(ValidationId, bytes32, PackedUserOperation memory, bytes calldata) returns(uint256) validateUserOpFn; (vMode, vType, vId) = parseNonce(userOp.nonce); - signature = userOp.signature; + + bytes calldata signature = userOp.signature; if (isEnable(vMode)) { bool enableReplayable = isEnableReplayable(vMode); EnableModeSignature calldata sig; assembly { sig := signature.offset } - require( - _verifyInstallSignature(enableReplayable, sig.packages, sig.enableSignature), InvalidEnableSignature() - ); + validationData = _verifyInstallSignatureRaw(enableReplayable, sig.nonce, sig.packages, sig.enableSignature); _install(sig.packages); signature = sig.userOpSignature; } (vId, validateUserOpFn) = _checkValidation(vMode, vType, vId); - opHash = isReplayable(vMode) ? Lib4337.chainAgnosticUserOpHash(msg.sender, userOp) : userOpHash; + bytes32 opHash = isReplayable(vMode) ? Lib4337.chainAgnosticUserOpHash(msg.sender, userOp) : userOpHash; + validationData = + Lib4337.intersectValidationData(validationData, validateUserOpFn(vId, opHash, userOp, signature)); } function isValidSignature(bytes32 hash, bytes calldata signature) external view returns (bytes4) { - bool replayable = bytes1(signature[0]) == 0xff; - ValidationId vId = ValidationId.wrap(bytes20(signature[1:21])); - _verifySignature(vId, msg.sender, hash, signature[21:]); + ValidationId vId = ValidationId.wrap(bytes20(signature[0:20])); + uint256 validationData = _verifySignature(vId, msg.sender, hash, signature[20:]); + return Lib4337.checkValidation(validationData) ? ERC1271_MAGICVALUE : ERC1271_INVALID; } /// execution - function executeUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash) - external - payable - onlyEntryPointOrSelf - { + function executeUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash) external payable { + _onlyEntryPointOrSelf(); (bool success, bytes memory ret) = address(this).delegatecall(userOp.callData[4:]); } - function execute(bytes32 mode, bytes calldata executionData) external payable onlyEntryPointOrSelf { + function execute(bytes32 mode, bytes calldata executionData) external payable { + _onlyEntryPointOrSelf(); _execute(mode, executionData); } - function executeFromExecutor(bytes32 mode, bytes calldata executionData) external payable onlyExecutor { + function executeFromExecutor(bytes32 mode, bytes calldata executionData) external payable { + _verifyExecutionData(mode, executionData); + _executeFromExecutor(mode, executionData); + } + + function _executeFromExecutor(bytes32 mode, bytes calldata executionData) internal executorHook { _execute(mode, executionData); } @@ -164,11 +162,8 @@ contract Kernel is ModuleManager, ExecutionManager, EIP712 { bytes internalData; } - function installModule(uint256 moduleType, address module, bytes calldata initData) - external - payable - onlyEntryPointOrSelf - { + function installModule(uint256 moduleType, address module, bytes calldata initData) external payable { + _onlyEntryPointOrSelf(); InstallModuleDataFormat calldata imdf; assembly { imdf := initData.offset @@ -176,11 +171,8 @@ contract Kernel is ModuleManager, ExecutionManager, EIP712 { _installModule(moduleType, module, imdf.installData, imdf.internalData); } - function uninstallModule(uint256 moduleType, address module, bytes calldata initData) - external - payable - onlyEntryPointOrSelf - { + function uninstallModule(uint256 moduleType, address module, bytes calldata initData) external payable { + _onlyEntryPointOrSelf(); InstallModuleDataFormat calldata imdf; assembly { imdf := initData.offset @@ -188,15 +180,20 @@ contract Kernel is ModuleManager, ExecutionManager, EIP712 { _uninstallModule(moduleType, module, imdf.installData, imdf.internalData); } - function setRoot(ValidationId vId) external payable onlyEntryPointOrSelf { + function setRoot(ValidationId vId) external payable { + _onlyEntryPointOrSelf(); _setRoot(vId); } // NOTE : this ONLY allows root signature, for now - function installModule(bool replayable, Install[] calldata packages, bytes calldata signature) external { + function installModule(bool replayable, uint256 nonce, Install[] calldata packages, bytes calldata signature) + external + { if (_initialized()) { // if 7702 or already initialized, use root signature to install module - require(_verifyInstallSignature(replayable, packages, signature), InstallSignatureVerificationFailed()); + require( + _verifyInstallSignature(replayable, nonce, packages, signature), InstallSignatureVerificationFailed() + ); _install(packages); } else { // this is initialize @@ -208,27 +205,6 @@ contract Kernel is ModuleManager, ExecutionManager, EIP712 { } } - function _verifyInstallSignature(bool replayable, Install[] calldata packages, bytes calldata signature) - internal - view - returns (bool success) - { - ValidationId vId = _validationStorage().root; - function(bytes32) internal view returns(bytes32) hashTypedData = - replayable ? _hashTypedDataSansChainId : _hashTypedData; - bytes32 digest = hashTypedData( - keccak256( - abi.encode( - keccak256( - "InstallPackages(Install[] packages)Install(uint256 moduleType,address module,bytes moduleData,bytes internalData)" - ), - _installHash(packages) - ) - ) - ); - return _verifySignature(vId, address(this), digest, signature) == ERC1271_MAGICVALUE ? true : false; - } - fallback(bytes calldata) external payable returns (bytes memory) { return _fallback(); } diff --git a/src/KernelFactory.sol b/src/KernelFactory.sol index 9464572a..912a8382 100644 --- a/src/KernelFactory.sol +++ b/src/KernelFactory.sol @@ -18,23 +18,25 @@ contract KernelFactory { if (deployed) { return k; } - k.installModule(true, initialPackages, hex""); + k.installModule(true, 0, initialPackages, hex""); return k; } - function deployWithAdditionalPackage( - Install[] calldata initialPackages, - uint256 nonce, - bool replayable, - Install[] calldata packages, - bytes calldata signature - ) external payable returns (Kernel) { - bytes32 salt = keccak256(abi.encode(initialPackages, nonce)); - (bool deployed, address account) = LibClone.createDeterministicERC1967(msg.value, address(template), salt); - - Kernel k = Kernel(payable(account)); - k.installModule(true, initialPackages, hex""); - k.installModule(replayable, packages, signature); - return k; - } + // function deployWithAdditionalPackage( + // Install[] calldata initialPackages, + // uint256 nonce, + // bool replayable, + // uint256 packageNonce, + // Install[] calldata packages, + // bytes calldata signature + // ) external payable returns (Kernel) { + // bytes32 salt = keccak256(abi.encode(initialPackages, nonce)); + // (bool deployed, address account) = LibClone.createDeterministicERC1967(msg.value, address(template), salt); + // Kernel k = Kernel(payable(account)); + // if(!deployed) { + // k.installModule(true, 0, initialPackages, hex""); + // } + // k.installModule(replayable, packageNonce, packages, signature); + // return k; + // } } diff --git a/src/KernelHelper.sol b/src/KernelHelper.sol new file mode 100644 index 00000000..3a3ba281 --- /dev/null +++ b/src/KernelHelper.sol @@ -0,0 +1,90 @@ +pragma solidity ^0.8.0; + +import "./types/Structs.sol"; +import {IERC5267} from "./interfaces/IERC5267.sol"; +import "./lib/Utils.sol"; + +contract KernelHelper { + /// @dev `keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)")`. + bytes32 internal constant _DOMAIN_TYPEHASH = 0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f; + + /// @dev `keccak256("EIP712Domain(string name,string version,address verifyingContract)")`. + /// This is only used in `_hashTypedDataSansChainId`. + bytes32 internal constant _DOMAIN_TYPEHASH_SANS_CHAIN_ID = + 0x91ab3d17e3a50a9d89e63fd30b92be7f5336b03b287bb946787a83a9d62a2766; + + function installDigest(address kernel, bool replayable, uint256 nonce, Install[] calldata packages) + external + view + returns (bytes32 digest) + { + function(address, bytes32) internal view returns(bytes32) hashTypedData = + replayable ? _hashTypedDataSansChainId : _hashTypedData; + digest = hashTypedData( + kernel, + keccak256( + abi.encode( + keccak256( + "InstallPackages(uint256 nonce,Install[] packages)Install(uint256 moduleType,address module,bytes moduleData,bytes internalData)" + ), + nonce, + _installHash(packages) + ) + ) + ); + } + + function _installHash(Install[] calldata packages) internal pure returns (bytes32) { + bytes32[] memory packageHashes = new bytes32[](packages.length); + for (uint256 i = 0; i < packages.length; i++) { + Install calldata pkg = packages[i]; + packageHashes[i] = keccak256( + abi.encode(pkg.moduleType, pkg.module, calldataKeccak(pkg.moduleData), calldataKeccak(pkg.internalData)) + ); + } + return keccak256(abi.encodePacked(packageHashes)); + } + + function _hashTypedDataSansChainId(address addr, bytes32 structHash) public view returns (bytes32 digest) { + (, string memory name, string memory version,,,,) = IERC5267(addr).eip712Domain(); + /// @solidity memory-safe-assembly + assembly { + let m := mload(0x40) // Load the free memory pointer. + mstore(0x00, _DOMAIN_TYPEHASH_SANS_CHAIN_ID) + mstore(0x20, keccak256(add(name, 0x20), mload(name))) + mstore(0x40, keccak256(add(version, 0x20), mload(version))) + mstore(0x60, addr) + // Compute the digest. + mstore(0x20, keccak256(0x00, 0x80)) // Store the domain separator. + mstore(0x00, 0x1901) // Store "\x19\x01". + mstore(0x40, structHash) // Store the struct hash. + digest := keccak256(0x1e, 0x42) + mstore(0x40, m) // Restore the free memory pointer. + mstore(0x60, 0) // Restore the zero pointer. + } + } + + function _hashTypedData(address addr, bytes32 structHash) internal view virtual returns (bytes32 digest) { + // We will use `digest` to store the domain separator to save a bit of gas. + (, string memory name, string memory version,,,,) = IERC5267(addr).eip712Domain(); + bytes32 separator = keccak256(bytes(name)); + bytes32 versionHash = keccak256(bytes(version)); + /// @solidity memory-safe-assembly + assembly { + let m := mload(0x40) // Load the free memory pointer. + mstore(m, _DOMAIN_TYPEHASH) + mstore(add(m, 0x20), separator) // Name hash. + mstore(add(m, 0x40), versionHash) + mstore(add(m, 0x60), chainid()) + mstore(add(m, 0x80), address()) + separator := keccak256(m, 0xa0) + // Compute the digest. + mstore(0x00, 0x1901000000000000) // Store "\x19\x01". + mstore(0x1a, digest) // Store the domain separator. + mstore(0x3a, structHash) // Store the struct hash. + digest := keccak256(0x18, 0x42) + // Restore the part of the free memory slot that was overwritten. + mstore(0x3a, 0) + } + } +} diff --git a/src/core/ModuleManager.sol b/src/core/ModuleManager.sol index 78d24c0e..ff790626 100644 --- a/src/core/ModuleManager.sol +++ b/src/core/ModuleManager.sol @@ -5,22 +5,21 @@ import {ValidationManager} from "./ValidationManager.sol"; import {ExecutorManager} from "./ExecutorManager.sol"; import {HookManager} from "./HookManager.sol"; import {SelectorManager} from "./SelectorManager.sol"; +import {EIP712} from "solady/utils/EIP712.sol"; import "../types/Error.sol"; import "../types/Events.sol"; import "../types/Structs.sol"; +import "../types/Constants.sol"; import "../types/Types.sol"; +import "../lib/Utils.sol"; +import "../lib/Lib4337.sol"; -function calldataKeccak(bytes calldata data) pure returns (bytes32 ret) { - assembly ("memory-safe") { - let mem := mload(0x40) - let len := data.length - calldatacopy(mem, data.offset, len) - ret := keccak256(mem, len) - } +struct ModuleStorage { + mapping(uint192 key => uint64) nonce; } -contract ModuleManager is ValidationManager, ExecutorManager, HookManager, SelectorManager { - modifier onlyExecutor() { +abstract contract ModuleManager is ValidationManager, ExecutorManager, HookManager, SelectorManager, EIP712 { + modifier executorHook() { IHook hook = _executorConfig(IExecutor(msg.sender)).hook; bytes memory hookData = _preHook(hook); _; @@ -32,6 +31,12 @@ contract ModuleManager is ValidationManager, ExecutorManager, HookManager, Selec || ValidationId.unwrap(_validationStorage().root) != bytes20(0); } + function _moduleStorage() internal view returns (ModuleStorage storage $) { + assembly { + $.slot := MODULE_MANAGER_STORAGE_SLOT + } + } + function _installHash(Install[] calldata packages) internal pure returns (bytes32) { bytes32[] memory packageHashes = new bytes32[](packages.length); for (uint256 i = 0; i < packages.length; i++) { @@ -89,7 +94,7 @@ contract ModuleManager is ValidationManager, ExecutorManager, HookManager, Selec revert NotImplemented(); } _uninstall(module, moduleData, internalData, hook); - emit ModuleInstalled(moduleType, module); + emit ModuleUninstalled(moduleType, module); } function _install(Install[] calldata packages) internal { @@ -120,4 +125,43 @@ contract ModuleManager is ValidationManager, ExecutorManager, HookManager, Selec (bool success,) = module.call(abi.encodeWithSelector(IModule.onUninstall.selector, data)); hook(module, internalData, success); } + + function _verifyExecutionData( + bytes32 mode, + bytes calldata callData + ) internal view returns(bool success) { + } + + function _verifyInstallSignature( + bool replayable, + uint256 nonce, + Install[] calldata packages, + bytes calldata signature + ) internal view returns (bool success) { + uint256 validationData = _verifyInstallSignatureRaw(replayable, nonce, packages, signature); + return Lib4337.checkValidation(validationData); + } + + function _verifyInstallSignatureRaw( + bool replayable, + uint256 nonce, + Install[] calldata packages, + bytes calldata signature + ) internal view returns (uint256 validationData) { + ValidationId vId = _validationStorage().root; + function(bytes32) internal view returns(bytes32) hashTypedData = + replayable ? _hashTypedDataSansChainId : _hashTypedData; + bytes32 digest = hashTypedData( + keccak256( + abi.encode( + keccak256( + "InstallPackages(uint256 nonce,Install[] packages)Install(uint256 moduleType,address module,bytes moduleData,bytes internalData)" + ), + nonce, + _installHash(packages) + ) + ) + ); + return _verifySignature(vId, address(this), digest, signature); + } } diff --git a/src/core/ValidationManager.sol b/src/core/ValidationManager.sol index 33eebb96..d7205fa1 100644 --- a/src/core/ValidationManager.sol +++ b/src/core/ValidationManager.sol @@ -16,16 +16,10 @@ function getValidator(ValidationId vId) pure returns (address v) { } } -function getType(ValidationId validator) pure returns (ValidationType vType) { - assembly { - vType := validator - } -} - function parseNonce(uint256 nonce) pure returns (ValidationMode vMode, ValidationType vType, ValidationId vId) { // 2bytes mode (1byte currentMode, 1byte type) // 20bytes identifier - // 1byte mode | 1byte type | 20bytes vId | 2byte nonceKey | 8byte nonce == 32bytes + // 1byte mode | 1byte type | 20bytes vId | 2byte nonceKey | 8byte nonce == 32bytes assembly { vMode := nonce vType := shl(8, nonce) @@ -36,7 +30,7 @@ function parseNonce(uint256 nonce) pure returns (ValidationMode vMode, Validatio abstract contract ValidationManager { ValidationId transient installingPermission; - function validationInfo(ValidationId vId) external view returns(ValidationInfo memory) { + function validationInfo(ValidationId vId) external view returns (ValidationInfo memory) { ValidationStorage storage $ = _validationStorage(); return $.vInfo[vId]; } @@ -66,7 +60,10 @@ abstract contract ValidationManager { installingPermission = ValidationId.wrap(bytes20(0)); } - function _checkPermissionInstall(bytes calldata _internalData, bool _installSuccess) internal returns(ValidationInfo storage $) { + function _checkPermissionInstall(bytes calldata _internalData, bool _installSuccess) + internal + returns (ValidationInfo storage $) + { require(_installSuccess, ModuleInstallFailed()); ValidationId vId = ValidationId.wrap(bytes20(_internalData[0:20])); $ = _validationStorage().vInfo[vId]; @@ -90,8 +87,13 @@ abstract contract ValidationManager { ValidationId vId = ValidationId.wrap(bytes20(_internalData[0:20])); ValidationInfo storage $ = _validationStorage().vInfo[vId]; $ = _validationStorage().vInfo[vId]; - require($.policies[$.policies.length - 1] == _policy, InvalidPermissionUninstallOrder()); - $.policies.pop(); + unchecked { + require($.policies[$.policies.length - 1] == _policy, InvalidPermissionUninstallOrder()); + $.policies.pop(); + } + if($.signer == address(0)) { + $.vType = VALIDATION_TYPE_ROOT; + } } function _uninstallSigner(address _signer, bytes calldata _internalData, bool _uninstallSuccess) internal { @@ -108,8 +110,7 @@ abstract contract ValidationManager { view returns ( ValidationId v, - function(ValidationId, bytes32, PackedUserOperation calldata, bytes calldata) internal returns(uint256) - validateUserOp + function(ValidationId, bytes32, PackedUserOperation memory, bytes calldata) internal returns(uint256) validateUserOp ) { ValidationStorage storage $ = _validationStorage(); @@ -133,19 +134,50 @@ abstract contract ValidationManager { function _verifySignature(ValidationId vId, address requester, bytes32 _hash, bytes calldata _signature) internal view - returns (bytes4) + returns (uint256 validationData) { if (ValidationId.unwrap(vId) == bytes20(0)) { - return _verify7702Signature(_hash, _signature) ? ERC1271_MAGICVALUE : ERC1271_INVALID; + return _verify7702Signature(_hash, _signature) ? 0 : 1; + } + IValidator validator = IValidator(address(ValidationId.unwrap(vId))); // TODO: add permission support; + validationData = validator.isValidSignatureWithSender(requester, /*NOTE: fix this */ _hash, _signature) + == ERC1271_MAGICVALUE ? 0 : 1; + } + + function _verifySignaturePermission(ValidationId vId, address requester, bytes32 _hash, bytes calldata _signature) + internal + view + returns (uint256 validationData) + { + ValidationInfo storage vInfo = _validationStorage().vInfo[vId]; + unchecked { + uint256 length = vInfo.policies.length + 1; + + PermissionSignature calldata permissionSig; + assembly { + permissionSig := _signature.offset + } + bytes32 paddedVId = bytes32(ValidationId.unwrap(vId)); + for (uint256 i = 0; i < vInfo.policies.length; i++) { + IPolicy policy = IPolicy(vInfo.policies[i]); + validationData = Lib4337.intersectValidationData( + validationData, + policy.checkSignaturePolicy(paddedVId, requester, _hash, permissionSig.signatures[i]) + ); + } + validationData = Lib4337.intersectValidationData( + validationData, + ISigner(vInfo.signer).checkSignature( + paddedVId, requester, _hash, permissionSig.signatures[permissionSig.signatures.length - 1] + ) == ERC1271_MAGICVALUE ? 0 : 1 + ); } - IValidator validator = IValidator(getValidator(vId)); // TODO: add permission support; - return validator.isValidSignatureWithSender(requester, /*NOTE: fix this */ _hash, _signature); } function _validateUserOpValidator( ValidationId vId, bytes32 opHash, - PackedUserOperation calldata op, + PackedUserOperation memory op, bytes calldata userOpSignature ) internal returns (uint256 validationData) { if (ValidationId.unwrap(vId) == bytes20(0)) { @@ -153,9 +185,8 @@ abstract contract ValidationManager { } // NOTE: removed permission for now, adding back after testing is done address validator = address(ValidationId.unwrap(vId)); - PackedUserOperation memory modifiedOp = op; - modifiedOp.signature = userOpSignature; - return IValidator(validator).validateUserOp(modifiedOp, opHash); + op.signature = userOpSignature; + return IValidator(validator).validateUserOp(op, opHash); } struct PermissionSignature { @@ -165,27 +196,29 @@ abstract contract ValidationManager { function _validateUserOpPermission( ValidationId vId, bytes32 opHash, - PackedUserOperation calldata op, + PackedUserOperation memory op, bytes calldata userOpSignature ) internal returns (uint256 validationData) { ValidationInfo storage vInfo = _validationStorage().vInfo[vId]; unchecked { - uint256 length = vInfo.policies.length + 1; + uint256 length = vInfo.policies.length + 1; - PermissionSignature calldata permissionSig; - assembly { - permissionSig := userOpSignature.offset - } - PackedUserOperation memory modifiedOp = op; - bytes32 paddedVId = bytes32(ValidationId.unwrap(vId)); - for (uint256 i = 0; i < vInfo.policies.length; i++) { - IPolicy policy = IPolicy(vInfo.policies[i]); - modifiedOp.signature = permissionSig.signatures[i]; - validationData = _intersectValidationData(validationData, policy.checkUserOpPolicy(paddedVId, modifiedOp)); - } + PermissionSignature calldata permissionSig; + assembly { + permissionSig := userOpSignature.offset + } + bytes32 paddedVId = bytes32(ValidationId.unwrap(vId)); + for (uint256 i = 0; i < vInfo.policies.length; i++) { + IPolicy policy = IPolicy(vInfo.policies[i]); + op.signature = permissionSig.signatures[i]; + validationData = + Lib4337.intersectValidationData(validationData, policy.checkUserOpPolicy(paddedVId, op)); + } - modifiedOp.signature = permissionSig.signatures[permissionSig.signatures.length - 1]; - return _intersectValidationData(validationData, ISigner(vInfo.signer).checkUserOpSignature(paddedVId, modifiedOp, opHash)); + op.signature = permissionSig.signatures[permissionSig.signatures.length - 1]; + return Lib4337.intersectValidationData( + validationData, ISigner(vInfo.signer).checkUserOpSignature(paddedVId, op, opHash) + ); } } @@ -209,37 +242,4 @@ abstract contract ValidationManager { ValidationStorage storage $ = _validationStorage(); $.root = vId; } - - function _intersectValidationData(uint256 a, uint256 b) internal pure returns (uint256 validationData) { - assembly { - // xor(a,b) == shows only matching bits - // and(xor(a,b), 0x000000000000000000000000ffffffffffffffffffffffffffffffffffffffff) == filters out the validAfter and validUntil bits - // if the result is not zero, then aggregator part is not matching - // validCase : - // a == 0 || b == 0 || xor(a,b) == 0 - // invalidCase : - // a mul b != 0 && xor(a,b) != 0 - let sum := shl(96, add(a, b)) - switch or( - iszero(and(xor(a, b), 0x000000000000000000000000ffffffffffffffffffffffffffffffffffffffff)), - or(eq(sum, shl(96, a)), eq(sum, shl(96, b))) - ) - case 1 { - validationData := and(or(a, b), 0x000000000000000000000000ffffffffffffffffffffffffffffffffffffffff) - // validAfter - let a_vd := and(0xffffffffffff0000000000000000000000000000000000000000000000000000, a) - let b_vd := and(0xffffffffffff0000000000000000000000000000000000000000000000000000, b) - validationData := or(validationData, xor(a_vd, mul(xor(a_vd, b_vd), gt(b_vd, a_vd)))) - // validUntil - a_vd := and(0x000000000000ffffffffffff0000000000000000000000000000000000000000, a) - if iszero(a_vd) { a_vd := 0x000000000000ffffffffffff0000000000000000000000000000000000000000 } - b_vd := and(0x000000000000ffffffffffff0000000000000000000000000000000000000000, b) - if iszero(b_vd) { b_vd := 0x000000000000ffffffffffff0000000000000000000000000000000000000000 } - let until := xor(a_vd, mul(xor(a_vd, b_vd), lt(b_vd, a_vd))) - if iszero(until) { until := 0x000000000000ffffffffffff0000000000000000000000000000000000000000 } - validationData := or(validationData, until) - } - default { validationData := SIG_VALIDATION_FAILED_UINT } - } - } } diff --git a/src/interfaces/IERC5267.sol b/src/interfaces/IERC5267.sol new file mode 100644 index 00000000..f9a66d4d --- /dev/null +++ b/src/interfaces/IERC5267.sol @@ -0,0 +1,16 @@ +pragma solidity ^0.8.0; + +interface IERC5267 { + function eip712Domain() + external + view + returns ( + bytes1 fields, + string memory name, + string memory version, + uint256 chainId, + address verifyingContract, + bytes32 salt, + uint256[] memory extensions + ); +} diff --git a/src/lib/Lib4337.sol b/src/lib/Lib4337.sol index f6ab120f..219804fb 100644 --- a/src/lib/Lib4337.sol +++ b/src/lib/Lib4337.sol @@ -3,33 +3,41 @@ pragma solidity ^0.8.0; import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; import {UserOperationLib} from "account-abstraction/core/UserOperationLib.sol"; import {Eip7702Support} from "account-abstraction/core/Eip7702Support.sol"; -import {SIG_VALIDATION_FAILED_UINT} from "../types/Constants.sol"; +import {ERC1271_MAGICVALUE, SIG_VALIDATION_FAILED_UINT} from "../types/Constants.sol"; import {ValidationData} from "../types/Types.sol"; - -interface IERC5267 { - function eip712Domain() - external - view - returns ( - bytes1 fields, - string memory name, - string memory version, - uint256 chainId, - address verifyingContract, - bytes32 salt, - uint256[] memory extensions - ); -} +import {IERC5267} from "../interfaces/IERC5267.sol"; library Lib4337 { bytes32 internal constant _DOMAIN_TYPEHASH_SANS_CHAIN_ID = 0x91ab3d17e3a50a9d89e63fd30b92be7f5336b03b287bb946787a83a9d62a2766; - function chainAgnosticUserOpHash(address ep, PackedUserOperation calldata userOp) public view returns (bytes32) { + function chainAgnosticUserOpHash(address ep, PackedUserOperation calldata userOp) external view returns (bytes32) { bytes32 overrideInitCodeHash = Eip7702Support._getEip7702InitCodeHashOverride(userOp); return _hashTypedDataSansChainId(ep, UserOperationLib.hash(userOp, overrideInitCodeHash)); } + function parseValidationData(uint256 validationData) + internal + pure + returns (uint48 validAfter, uint48 validUntil, address result) + { + assembly { + result := validationData + validUntil := and(shr(160, validationData), 0xffffffffffff) + switch iszero(validUntil) + case 1 { validUntil := 0xffffffffffff } + validAfter := shr(208, validationData) + } + } + + function checkValidation(uint256 validationData) external view returns(bool) { + (uint48 vAfter, uint48 vUntil,address res) = Lib4337.parseValidationData(validationData); + if (vAfter > block.timestamp || vUntil < block.timestamp) { + return false; + } + return res == address(0); + } + /// @dev Variant of `_hashTypedData` that excludes the chain ID. /// Included for the niche use case of cross-chain workflows. function _hashTypedDataSansChainId(address addr, bytes32 structHash) internal view returns (bytes32 digest) { @@ -51,7 +59,15 @@ library Lib4337 { } } - function _intersectValidationData(ValidationData a, ValidationData b) internal pure returns (ValidationData validationData) { + function intersectValidationData(uint256 a, bytes4 res) external pure returns (uint256) { + return _intersectValidationData(a, signatureResultToValidationData(res)); + } + + function intersectValidationData(uint256 a, uint256 b) external pure returns (uint256 validationData) { + return _intersectValidationData(a, b); + } + + function _intersectValidationData(uint256 a, uint256 b) private pure returns (uint256 validationData) { assembly { // xor(a,b) == shows only matching bits // and(xor(a,b), 0x000000000000000000000000ffffffffffffffffffffffffffffffffffffffff) == filters out the validAfter and validUntil bits @@ -83,4 +99,8 @@ library Lib4337 { default { validationData := SIG_VALIDATION_FAILED_UINT } } } + + function signatureResultToValidationData(bytes4 res) public pure returns (uint256 validationData) { + return res == ERC1271_MAGICVALUE ? 0 : 1; + } } diff --git a/src/lib/Utils.sol b/src/lib/Utils.sol new file mode 100644 index 00000000..d933bdc3 --- /dev/null +++ b/src/lib/Utils.sol @@ -0,0 +1,10 @@ +pragma solidity ^0.8.0; + +function calldataKeccak(bytes calldata data) pure returns (bytes32 ret) { + assembly ("memory-safe") { + let mem := mload(0x40) + let len := data.length + calldatacopy(mem, data.offset, len) + ret := keccak256(mem, len) + } +} diff --git a/src/types/Constants.sol b/src/types/Constants.sol index 9eff24e9..c74ceaa9 100644 --- a/src/types/Constants.sol +++ b/src/types/Constants.sol @@ -24,6 +24,7 @@ ValidationType constant VALIDATION_TYPE_PERMISSION = ValidationType.wrap(0x02); // TODO: change this -- recalculate bytes32 constant SELECTOR_MANAGER_STORAGE_SLOT = 0x7c341349a4360fdd5d5bc07e69f325dc6aaea3eb018b3e0ea7e53cc0bb0d6f3b; +bytes32 constant MODULE_MANAGER_STORAGE_SLOT = 0x9bc558e75ed0a57385e96d6b87fd2864d462eed29668be6fed742168fd90ab0f; // bytes32(uint256(keccak256('kernel.v3.executor')) - 1) bytes32 constant EXECUTOR_MANAGER_STORAGE_SLOT = 0x1bbee3173dbdc223633258c9f337a0fff8115f206d302bea0ed3eac003b68b86; // bytes32(uint256(keccak256('kernel.v3.hook')) - 1) diff --git a/src/types/Types.sol b/src/types/Types.sol index 8594fa88..596c9530 100644 --- a/src/types/Types.sol +++ b/src/types/Types.sol @@ -39,19 +39,6 @@ function packValidationData(ValidAfter validAfter, ValidUntil validUntil) pure r return uint256(ValidAfter.unwrap(validAfter)) << 208 | uint256(ValidUntil.unwrap(validUntil)) << 160; } -function parseValidationData(uint256 validationData) - pure - returns (ValidAfter validAfter, ValidUntil validUntil, address result) -{ - assembly { - result := validationData - validUntil := and(shr(160, validationData), 0xffffffffffff) - switch iszero(validUntil) - case 1 { validUntil := 0xffffffffffff } - validAfter := shr(208, validationData) - } -} - using {vTypeEqual as ==} for ValidationType global; using {eqCallType as ==} for CallType global; using {notEqCallType as !=} for CallType global; diff --git a/test/Kernel.t.sol b/test/Kernel.t.sol index e0e67e37..5d9cd5c9 100644 --- a/test/Kernel.t.sol +++ b/test/Kernel.t.sol @@ -5,6 +5,7 @@ import {EntryPointLib} from "./utils/EntryPointLib.sol"; import {IEntryPoint} from "account-abstraction/interfaces/IEntryPoint.sol"; import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; import {Kernel} from "src/Kernel.sol"; +import {KernelHelper} from "src/KernelHelper.sol"; import {SelectorManager} from "src/core/SelectorManager.sol"; import {KernelFactory} from "src/KernelFactory.sol"; import {LibERC7579} from "solady/accounts/LibERC7579.sol"; @@ -67,11 +68,17 @@ contract KernelTest is Test { IEntryPoint ep; KernelFactory factory; MockValidator mockValidator; + MockValidator newValidator; Kernel kernel; MockCallee callee; MockFallback mockFallback; address executor; address payable beneficiary; + MockPolicy policy; + MockSigner signer; + bytes20 permissionId; + uint256 permissionRevertIndex; + KernelHelper helper; modifier unitTest() { vm.startPrank(address(ep)); @@ -92,11 +99,16 @@ contract KernelTest is Test { function setUp() external { ep = EntryPointLib.deploy(); factory = new KernelFactory(ep); + helper = new KernelHelper(); mockValidator = new MockValidator(); + newValidator = new MockValidator(); callee = new MockCallee(); executor = makeAddr("Executor"); mockFallback = new MockFallback(); beneficiary = payable(makeAddr("Beneficiary")); + policy = new MockPolicy(); + signer = new MockSigner(); + permissionId = bytes20(keccak256(abi.encodePacked("Hello world"))); _initialize(); } @@ -111,6 +123,97 @@ contract KernelTest is Test { vm.stopPrank(); } + function _rootSignUserOp(PackedUserOperation memory op, bool success) internal returns (bytes memory sig) { + mockValidator.sudoSetSuccess(success); + return hex""; + } + + function _rootSignHash(bytes32 hash, bool success) internal returns (bytes memory sig) { + if (success) { + mockValidator.sudoSetValidSig(hex""); + } + return hex""; + } + + function _validatorSignUserOp(PackedUserOperation memory op, bool success) internal returns (bytes memory sig) { + newValidator.sudoSetSuccess(success); + return hex""; + } + + function _validatorSignHash(bytes32 hash, bool success) internal returns (bytes memory sig) { + if (success) { + newValidator.sudoSetValidSig(hex""); + } + return hex""; + } + + function _permissionSignUserOp(PackedUserOperation memory op, bool success) internal returns (bytes memory sig) { + bytes[] memory signatures = new bytes[](2); + signatures[0] = hex"dead"; + signatures[1] = hex"beef"; + if (success || permissionRevertIndex != 0) { + policy.sudoSetValidSig(address(kernel), permissionId, hex"dead"); + } + if (success || permissionRevertIndex != 1) { + signer.sudoSetValidSig(address(kernel), permissionId, hex"beef"); + } + + return abi.encode(signatures); + } + + function _permissionSignHash(bytes32 hash, bool success) internal returns (bytes memory sig) {} + + function enableSig( + uint256 nonce, + bool enableSuccess, + bool replayable, + Install[] memory packages, + function(bytes32, bool) internal returns(bytes memory) signEnable + ) internal returns (bytes memory sig) { + bytes32 digest = helper.installDigest(address(kernel), replayable, nonce, packages); + return signEnable(digest, enableSuccess); + } + + function encodeEnableValidatorSignature( + uint256 nonce, + bool enableSuccess, + bool replayable, + function(bytes32, bool) internal returns(bytes memory) signEnable, + bytes memory userOpSig + ) internal returns (bytes memory sig) { + Install[] memory packages = new Install[](1); + packages[0] = Install({moduleType: 1, module: address(newValidator), moduleData: hex"", internalData: hex""}); + sig = abi.encode( + uint256(0), packages, enableSig(nonce, enableSuccess, replayable, packages, signEnable), userOpSig + ); + } + + function encodeEnablePermissionSignature( + uint256 nonce, + bool enableSuccess, + bool replayable, + function(bytes32, bool) internal returns(bytes memory) signEnable, + bytes memory userOpSig + ) internal returns (bytes memory sig) { + Install[] memory packages = new Install[](2); + packages[0] = Install({ + moduleType: 5, + module: address(policy), + moduleData: hex"", + internalData: abi.encodePacked(permissionId) + }); + packages[1] = Install({ + moduleType: 6, + module: address(signer), + moduleData: hex"", + internalData: abi.encodePacked(permissionId) + }); + + sig = abi.encode( + uint256(0), packages, enableSig(nonce, enableSuccess, replayable, packages, signEnable), userOpSig + ); + } + function encodeNonce(bool replayableUserOp, bool enableFlag, bool replayableEnable, bytes1 vType, bytes20 vId) internal returns (uint256 nonce) @@ -131,8 +234,9 @@ contract KernelTest is Test { function test_codesize() external { address implementation = address(factory.template()); - require(implementation.code.length <= 24576, "Code too big"); console.log("Code size :", implementation.code.length); + require(implementation.code.length <= 24576, "Code too big"); + console.log("space left :", 24576 - implementation.code.length); } function test_receive_eth() external { @@ -143,7 +247,7 @@ contract KernelTest is Test { vm.startPrank(sender); vm.expectEmit(k); emit Received(sender, uint256(1)); - (bool success, ) = k.call{value: 1}(hex""); + (bool success,) = k.call{value: 1}(hex""); require(success); vm.stopPrank(); @@ -153,10 +257,20 @@ contract KernelTest is Test { vm.startPrank(address(ep)); vm.expectEmit(k); emit Received(address(mock), uint256(1)); - kernel.execute(bytes32(0), abi.encodePacked(address(mock), uint256(0), abi.encodeWithSelector(MockContractETH.useTransfer.selector, k, uint256(1)))); + kernel.execute( + bytes32(0), + abi.encodePacked( + address(mock), uint256(0), abi.encodeWithSelector(MockContractETH.useTransfer.selector, k, uint256(1)) + ) + ); vm.expectEmit(k); emit Received(address(mock), uint256(1)); - kernel.execute(bytes32(0), abi.encodePacked(address(mock), uint256(0), abi.encodeWithSelector(MockContractETH.useSend.selector, k, uint256(1)))); + kernel.execute( + bytes32(0), + abi.encodePacked( + address(mock), uint256(0), abi.encodeWithSelector(MockContractETH.useSend.selector, k, uint256(1)) + ) + ); vm.stopPrank(); } @@ -179,9 +293,9 @@ contract KernelTest is Test { mock.mint(sender, 1, 1, hex"deadbeef"); vm.prank(sender); mock.safeTransferFrom(sender, address(kernel), 1, 1, hex"deadbeef"); - + mock.mint(address(kernel), 1, 1, hex"deadbeef"); - + mock.mint(sender, 2, 4, hex"deadbeef"); mock.mint(sender, 3, 5, hex"deadbeef"); uint256[] memory ids = new uint256[](2); @@ -212,7 +326,7 @@ contract KernelTest is Test { paymasterAndData: hex"", signature: hex"" }); - mockValidator.sudoSetSuccess(true); + ops[0].signature = _rootSignUserOp(ops[0], true); ep.handleOps(ops, beneficiary); assertEq(callee.bar(), 1); } @@ -232,13 +346,12 @@ contract KernelTest is Test { paymasterAndData: hex"", signature: hex"" }); - mockValidator.sudoSetSuccess(false); + ops[0].signature = _rootSignUserOp(ops[0], false); vm.expectRevert(abi.encodeWithSelector(IEntryPoint.FailedOp.selector, 0, "AA24 signature error")); ep.handleOps(ops, beneficiary); } function test_userop_validator_aa24_notinstalled() external entryPointTest { - MockValidator newValidator = new MockValidator(); PackedUserOperation[] memory ops = new PackedUserOperation[](1); ops[0] = PackedUserOperation({ sender: address(kernel), @@ -253,14 +366,12 @@ contract KernelTest is Test { paymasterAndData: hex"", signature: hex"" }); - mockValidator.sudoSetSuccess(false); - newValidator.sudoSetSuccess(true); + ops[0].signature = _validatorSignUserOp(ops[0], true); vm.expectRevert(abi.encodeWithSelector(IEntryPoint.FailedOp.selector, 0, "AA24 signature error")); ep.handleOps(ops, beneficiary); } function test_userop_validator_use_root_if_notinstalled() external entryPointTest { - MockValidator newValidator = new MockValidator(); PackedUserOperation[] memory ops = new PackedUserOperation[](1); ops[0] = PackedUserOperation({ sender: address(kernel), @@ -275,14 +386,12 @@ contract KernelTest is Test { paymasterAndData: hex"", signature: hex"" }); - mockValidator.sudoSetSuccess(true); - newValidator.sudoSetSuccess(false); + ops[0].signature = _rootSignUserOp(ops[0], true); ep.handleOps(ops, beneficiary); assertEq(callee.bar(), 1); } function test_userop_validator_enable() external entryPointTest { - MockValidator newValidator = new MockValidator(); PackedUserOperation[] memory ops = new PackedUserOperation[](1); ops[0] = PackedUserOperation({ sender: address(kernel), @@ -297,22 +406,13 @@ contract KernelTest is Test { paymasterAndData: hex"", signature: hex"" }); - - Install[] memory packages = new Install[](1); - packages[0] = Install({moduleType: 1, module: address(newValidator), moduleData: hex"", internalData: hex""}); - - bytes memory sig = abi.encode(packages, hex"", hex""); - - ops[0].signature = sig; - mockValidator.sudoSetSuccess(false); - mockValidator.sudoSetValidSig(hex""); - newValidator.sudoSetSuccess(true); + ops[0].signature = + encodeEnableValidatorSignature(0, true, false, _rootSignHash, _validatorSignUserOp(ops[0], true)); ep.handleOps(ops, beneficiary); assertEq(callee.bar(), 1); } - function test_userop_validator_aa23_enable_fail_wrong_signature() external entryPointTest { - MockValidator newValidator = new MockValidator(); + function test_userop_validator_aa24_enable_fail_wrong_signature() external entryPointTest { PackedUserOperation[] memory ops = new PackedUserOperation[](1); ops[0] = PackedUserOperation({ sender: address(kernel), @@ -327,29 +427,13 @@ contract KernelTest is Test { paymasterAndData: hex"", signature: hex"" }); - - Install[] memory packages = new Install[](1); - packages[0] = Install({moduleType: 1, module: address(newValidator), moduleData: hex"", internalData: hex""}); - - bytes memory sig = abi.encode(packages, hex"", hex""); - - ops[0].signature = sig; - mockValidator.sudoSetSuccess(false); - newValidator.sudoSetSuccess(true); - newValidator.sudoSetValidSig(hex""); - vm.expectRevert( - abi.encodeWithSelector( - IEntryPoint.FailedOpWithRevert.selector, - 0, - "AA23 reverted", - abi.encodeWithSelector(InvalidEnableSignature.selector) - ) - ); + ops[0].signature = + encodeEnableValidatorSignature(0, false, false, _rootSignHash, _validatorSignUserOp(ops[0], true)); + vm.expectRevert(abi.encodeWithSelector(IEntryPoint.FailedOp.selector, 0, "AA24 signature error")); ep.handleOps(ops, beneficiary); } function test_userop_validator_aa24_validation_failed() external entryPointTest { - MockValidator newValidator = new MockValidator(); PackedUserOperation[] memory ops = new PackedUserOperation[](1); ops[0] = PackedUserOperation({ sender: address(kernel), @@ -365,23 +449,13 @@ contract KernelTest is Test { signature: hex"" }); - Install[] memory packages = new Install[](1); - packages[0] = Install({moduleType: 1, module: address(newValidator), moduleData: hex"", internalData: hex""}); - - bytes memory sig = abi.encode(packages, hex"", hex""); - - ops[0].signature = sig; - mockValidator.sudoSetSuccess(false); - newValidator.sudoSetSuccess(false); - mockValidator.sudoSetValidSig(hex""); + ops[0].signature = + encodeEnableValidatorSignature(0, true, false, _rootSignHash, _validatorSignUserOp(ops[0], false)); vm.expectRevert(abi.encodeWithSelector(IEntryPoint.FailedOp.selector, 0, "AA24 signature error")); ep.handleOps(ops, beneficiary); } function test_userop_permission_aa24_notinstalled() external entryPointTest { - MockPolicy policy = new MockPolicy(); - MockSigner signer = new MockSigner(); - bytes20 permissionId = bytes20(keccak256(abi.encodePacked("Hello world"))); PackedUserOperation[] memory ops = new PackedUserOperation[](1); ops[0] = PackedUserOperation({ sender: address(kernel), @@ -396,15 +470,12 @@ contract KernelTest is Test { paymasterAndData: hex"", signature: hex"" }); - mockValidator.sudoSetSuccess(false); + ops[0].signature = _permissionSignUserOp(ops[0], true); vm.expectRevert(abi.encodeWithSelector(IEntryPoint.FailedOp.selector, 0, "AA24 signature error")); ep.handleOps(ops, beneficiary); } function test_userop_permission_use_root_if_notinstalled() external entryPointTest { - MockPolicy policy = new MockPolicy(); - MockSigner signer = new MockSigner(); - bytes20 permissionId = bytes20(keccak256(abi.encodePacked("Hello world"))); PackedUserOperation[] memory ops = new PackedUserOperation[](1); ops[0] = PackedUserOperation({ sender: address(kernel), @@ -419,15 +490,12 @@ contract KernelTest is Test { paymasterAndData: hex"", signature: hex"" }); - mockValidator.sudoSetSuccess(true); + ops[0].signature = _rootSignUserOp(ops[0], true); ep.handleOps(ops, beneficiary); assertEq(callee.bar(), 1); } function test_userop_permission_enable() external entryPointTest { - MockPolicy policy = new MockPolicy(); - MockSigner signer = new MockSigner(); - bytes20 permissionId = bytes20(keccak256(abi.encodePacked("Hello world"))); PackedUserOperation[] memory ops = new PackedUserOperation[](1); ops[0] = PackedUserOperation({ sender: address(kernel), @@ -443,40 +511,13 @@ contract KernelTest is Test { signature: hex"" }); - Install[] memory packages = new Install[](2); - packages[0] = Install({ - moduleType: 5, - module: address(policy), - moduleData: hex"", - internalData: abi.encodePacked(permissionId) - }); - packages[1] = Install({ - moduleType: 6, - module: address(signer), - moduleData: hex"", - internalData: abi.encodePacked(permissionId) - }); - - bytes[] memory signatures = new bytes[](2); - signatures[0] = hex""; - signatures[1] = hex""; - - bytes memory sig = abi.encode(packages, hex"", abi.encode(signatures)); - - ops[0].signature = sig; - mockValidator.sudoSetSuccess(false); - mockValidator.sudoSetValidSig(hex""); - - policy.sudoSetValidSig(address(kernel), bytes32(abi.encodePacked(permissionId)), hex""); - signer.sudoSetValidSig(address(kernel), bytes32(abi.encodePacked(permissionId)), hex""); + ops[0].signature = + encodeEnablePermissionSignature(0, true, false, _rootSignHash, _permissionSignUserOp(ops[0], true)); ep.handleOps(ops, beneficiary); assertEq(callee.bar(), 1); } - function test_userop_permission_aa23_enable_fail_wrong_signature() external entryPointTest { - MockPolicy policy = new MockPolicy(); - MockSigner signer = new MockSigner(); - bytes20 permissionId = bytes20(keccak256(abi.encodePacked("Hello world"))); + function test_userop_permission_aa24_enable_fail_wrong_signature() external entryPointTest { PackedUserOperation[] memory ops = new PackedUserOperation[](1); ops[0] = PackedUserOperation({ sender: address(kernel), @@ -491,46 +532,13 @@ contract KernelTest is Test { paymasterAndData: hex"", signature: hex"" }); - - Install[] memory packages = new Install[](2); - packages[0] = Install({ - moduleType: 5, - module: address(policy), - moduleData: hex"", - internalData: abi.encodePacked(permissionId) - }); - packages[1] = Install({ - moduleType: 6, - module: address(signer), - moduleData: hex"", - internalData: abi.encodePacked(permissionId) - }); - - bytes[] memory signatures = new bytes[](2); - signatures[0] = hex""; - signatures[1] = hex""; - - bytes memory sig = abi.encode(packages, hex"", abi.encode(signatures)); - - ops[0].signature = sig; - mockValidator.sudoSetSuccess(false); - policy.sudoSetValidSig(address(kernel), bytes32(abi.encodePacked(permissionId)), hex""); - signer.sudoSetValidSig(address(kernel), bytes32(abi.encodePacked(permissionId)), hex""); - vm.expectRevert( - abi.encodeWithSelector( - IEntryPoint.FailedOpWithRevert.selector, - 0, - "AA23 reverted", - abi.encodeWithSelector(InvalidEnableSignature.selector) - ) - ); + ops[0].signature = + encodeEnablePermissionSignature(0, false, false, _rootSignHash, _permissionSignUserOp(ops[0], true)); + vm.expectRevert(abi.encodeWithSelector(IEntryPoint.FailedOp.selector, 0, "AA24 signature error")); ep.handleOps(ops, beneficiary); } - function test_userop_permission_aa23_policy_failed() external entryPointTest { - MockPolicy policy = new MockPolicy(); - MockSigner signer = new MockSigner(); - bytes20 permissionId = bytes20(keccak256(abi.encodePacked("Hello world"))); + function test_userop_permission_aa24_policy_failed() external entryPointTest { PackedUserOperation[] memory ops = new PackedUserOperation[](1); ops[0] = PackedUserOperation({ sender: address(kernel), @@ -545,40 +553,13 @@ contract KernelTest is Test { paymasterAndData: hex"", signature: hex"" }); - - Install[] memory packages = new Install[](2); - packages[0] = Install({ - moduleType: 5, - module: address(policy), - moduleData: hex"", - internalData: abi.encodePacked(permissionId) - }); - packages[1] = Install({ - moduleType: 6, - module: address(signer), - moduleData: hex"", - internalData: abi.encodePacked(permissionId) - }); - - bytes[] memory signatures = new bytes[](2); - signatures[0] = hex""; - signatures[1] = hex""; - - bytes memory sig = abi.encode(packages, hex"", abi.encode(signatures)); - - ops[0].signature = sig; - mockValidator.sudoSetSuccess(false); - mockValidator.sudoSetValidSig(hex""); - policy.sudoSetValidSig(address(kernel), bytes32(abi.encodePacked(permissionId)), hex"deadbeef"); - signer.sudoSetValidSig(address(kernel), bytes32(abi.encodePacked(permissionId)), hex""); + ops[0].signature = + encodeEnablePermissionSignature(0, true, false, _rootSignHash, _permissionSignUserOp(ops[0], false)); vm.expectRevert(abi.encodeWithSelector(IEntryPoint.FailedOp.selector, 0, "AA24 signature error")); ep.handleOps(ops, beneficiary); } function test_userop_permission_aa24_signer_validation_failed() external entryPointTest { - MockPolicy policy = new MockPolicy(); - MockSigner signer = new MockSigner(); - bytes20 permissionId = bytes20(keccak256(abi.encodePacked("Hello world"))); PackedUserOperation[] memory ops = new PackedUserOperation[](1); ops[0] = PackedUserOperation({ sender: address(kernel), @@ -593,32 +574,9 @@ contract KernelTest is Test { paymasterAndData: hex"", signature: hex"" }); - - Install[] memory packages = new Install[](2); - packages[0] = Install({ - moduleType: 5, - module: address(policy), - moduleData: hex"", - internalData: abi.encodePacked(permissionId) - }); - packages[1] = Install({ - moduleType: 6, - module: address(signer), - moduleData: hex"", - internalData: abi.encodePacked(permissionId) - }); - - bytes[] memory signatures = new bytes[](2); - signatures[0] = hex""; - signatures[1] = hex""; - - bytes memory sig = abi.encode(packages, hex"", abi.encode(signatures)); - - ops[0].signature = sig; - mockValidator.sudoSetSuccess(false); - mockValidator.sudoSetValidSig(hex""); - policy.sudoSetValidSig(address(kernel), bytes32(abi.encodePacked(permissionId)), hex""); - signer.sudoSetValidSig(address(kernel), bytes32(abi.encodePacked(permissionId)), hex"deadbeef"); + permissionRevertIndex = 1; + ops[0].signature = + encodeEnablePermissionSignature(0, true, false, _rootSignHash, _permissionSignUserOp(ops[0], false)); vm.expectRevert(abi.encodeWithSelector(IEntryPoint.FailedOp.selector, 0, "AA24 signature error")); ep.handleOps(ops, beneficiary); } @@ -669,7 +627,6 @@ contract KernelTest is Test { } function test_install_validator() external unitTest { - MockValidator newValidator = new MockValidator(); ValidationId vId = ValidationId.wrap(bytes20(address(newValidator))); kernel.installModule(1, address(newValidator), abi.encode(hex"deadbeef", "InternalData")); ValidationInfo memory vInfo = kernel.validationInfo(vId); @@ -677,7 +634,6 @@ contract KernelTest is Test { } function test_uninstall_validator() external unitTest { - MockValidator newValidator = new MockValidator(); ValidationId vId = ValidationId.wrap(bytes20(address(newValidator))); kernel.installModule(1, address(newValidator), abi.encode(hex"deadbeef", "InternalData")); ValidationInfo memory vInfo = kernel.validationInfo(vId); @@ -687,6 +643,54 @@ contract KernelTest is Test { assertTrue(vInfo.vType == VALIDATION_TYPE_ROOT); } + function test_install_policy() external unitTest { + MockPolicy mock = new MockPolicy(); + ValidationId vId = ValidationId.wrap(bytes20(keccak256(abi.encodePacked("deadbeef")))); + ValidationInfo memory vInfo = kernel.validationInfo(vId); + assertTrue(vInfo.vType == VALIDATION_TYPE_ROOT); + kernel.installModule(5, address(mock), abi.encode(hex"deadbeef", abi.encodePacked(vId))); + vInfo = kernel.validationInfo(vId); + assertTrue(vInfo.vType == VALIDATION_TYPE_PERMISSION); + } + + function test_uninstall_policy() external unitTest { + MockPolicy mock = new MockPolicy(); + ValidationId vId = ValidationId.wrap(bytes20(keccak256(abi.encodePacked("deadbeef")))); + ValidationInfo memory vInfo = kernel.validationInfo(vId); + assertTrue(vInfo.vType == VALIDATION_TYPE_ROOT); + kernel.installModule(5, address(mock), abi.encode(hex"deadbeef", abi.encodePacked(vId))); + vInfo = kernel.validationInfo(vId); + assertTrue(vInfo.vType == VALIDATION_TYPE_PERMISSION); + kernel.uninstallModule(5, address(mock), abi.encode(hex"deadbeef", abi.encodePacked(vId))); + vInfo = kernel.validationInfo(vId); + assertTrue(vInfo.vType == VALIDATION_TYPE_ROOT); + } + + function test_install_signer() external unitTest { + MockSigner mock = new MockSigner(); + ValidationId vId = ValidationId.wrap(bytes20(keccak256(abi.encodePacked("deadbeef")))); + ValidationInfo memory vInfo = kernel.validationInfo(vId); + assertTrue(vInfo.vType == VALIDATION_TYPE_ROOT); + kernel.installModule(6, address(mock), abi.encode(hex"deadbeef", abi.encodePacked(vId))); + vInfo = kernel.validationInfo(vId); + assertTrue(vInfo.vType == VALIDATION_TYPE_PERMISSION); + } + + function test_uninstall_signer() external unitTest { + MockSigner mock = new MockSigner(); + ValidationId vId = ValidationId.wrap(bytes20(keccak256(abi.encodePacked("deadbeef")))); + ValidationInfo memory vInfo = kernel.validationInfo(vId); + assertTrue(vInfo.vType == VALIDATION_TYPE_ROOT); + kernel.installModule(6, address(mock), abi.encode(hex"deadbeef", abi.encodePacked(vId))); + vInfo = kernel.validationInfo(vId); + assertTrue(vInfo.vType == VALIDATION_TYPE_PERMISSION); + assertTrue(vInfo.signer == address(mock)); + kernel.uninstallModule(6, address(mock), abi.encode(hex"deadbeef", abi.encodePacked(vId))); + vInfo = kernel.validationInfo(vId); + assertTrue(vInfo.vType == VALIDATION_TYPE_ROOT); + assertTrue(vInfo.signer == address(0)); + } + function test_install_selector_call() external unitTest { kernel.installModule( 3, From 8a4d14a412864800538d83d30e9761b26d7edb51 Mon Sep 17 00:00:00 2001 From: leekt Date: Wed, 28 May 2025 02:29:13 +0900 Subject: [PATCH 017/121] no more via ir --- foundry.toml | 4 +- src/Kernel.sol | 4 +- src/core/ModuleManager.sol | 126 +++++++++++++++++++++++++++++---- src/core/ValidationManager.sol | 2 +- test/Kernel.t.sol | 53 ++++++++++++++ 5 files changed, 171 insertions(+), 18 deletions(-) diff --git a/foundry.toml b/foundry.toml index 83816a21..2c9d3a5b 100644 --- a/foundry.toml +++ b/foundry.toml @@ -2,6 +2,8 @@ src = "src" out = "out" libs = ["lib"] -via_ir = true +via_ir = false +optimizer = true +run = 200 # See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options diff --git a/src/Kernel.sol b/src/Kernel.sol index 0015302d..477357ca 100644 --- a/src/Kernel.sol +++ b/src/Kernel.sol @@ -90,10 +90,10 @@ contract Kernel is ModuleManager, ExecutionManager, UUPSUpgradeable { Lib4337.intersectValidationData(validationData, validateUserOpFn(vId, opHash, userOp, signature)); } - function isValidSignature(bytes32 hash, bytes calldata signature) external view returns (bytes4) { + function _erc1271IsValidSignatureNowCalldata(bytes32 hash, bytes calldata signature) internal view override returns(bool) { ValidationId vId = ValidationId.wrap(bytes20(signature[0:20])); uint256 validationData = _verifySignature(vId, msg.sender, hash, signature[20:]); - return Lib4337.checkValidation(validationData) ? ERC1271_MAGICVALUE : ERC1271_INVALID; + return Lib4337.checkValidation(validationData); } /// execution diff --git a/src/core/ModuleManager.sol b/src/core/ModuleManager.sol index ff790626..7d00e74b 100644 --- a/src/core/ModuleManager.sol +++ b/src/core/ModuleManager.sol @@ -5,7 +5,7 @@ import {ValidationManager} from "./ValidationManager.sol"; import {ExecutorManager} from "./ExecutorManager.sol"; import {HookManager} from "./HookManager.sol"; import {SelectorManager} from "./SelectorManager.sol"; -import {EIP712} from "solady/utils/EIP712.sol"; +import {ERC1271} from "solady/accounts/ERC1271.sol"; import "../types/Error.sol"; import "../types/Events.sol"; import "../types/Structs.sol"; @@ -15,10 +15,11 @@ import "../lib/Utils.sol"; import "../lib/Lib4337.sol"; struct ModuleStorage { + uint64 nonceValidFrom; mapping(uint192 key => uint64) nonce; } -abstract contract ModuleManager is ValidationManager, ExecutorManager, HookManager, SelectorManager, EIP712 { +abstract contract ModuleManager is ValidationManager, ExecutorManager, HookManager, SelectorManager, ERC1271 { modifier executorHook() { IHook hook = _executorConfig(IExecutor(msg.sender)).hook; bytes memory hookData = _preHook(hook); @@ -37,13 +38,19 @@ abstract contract ModuleManager is ValidationManager, ExecutorManager, HookManag } } + function _erc1271Signer() internal view override returns (address) { + return address(1); + } + function _installHash(Install[] calldata packages) internal pure returns (bytes32) { bytes32[] memory packageHashes = new bytes32[](packages.length); - for (uint256 i = 0; i < packages.length; i++) { - Install calldata pkg = packages[i]; - packageHashes[i] = keccak256( - abi.encode(pkg.moduleType, pkg.module, calldataKeccak(pkg.moduleData), calldataKeccak(pkg.internalData)) - ); + unchecked { + for (uint256 i = 0; i < packages.length; i++) { + Install calldata pkg = packages[i]; + packageHashes[i] = keccak256( + abi.encode(pkg.moduleType, pkg.module, calldataKeccak(pkg.moduleData), calldataKeccak(pkg.internalData)) + ); + } } return keccak256(abi.encodePacked(packageHashes)); } @@ -126,31 +133,33 @@ abstract contract ModuleManager is ValidationManager, ExecutorManager, HookManag hook(module, internalData, success); } - function _verifyExecutionData( - bytes32 mode, - bytes calldata callData - ) internal view returns(bool success) { - } function _verifyInstallSignature( bool replayable, uint256 nonce, Install[] calldata packages, bytes calldata signature - ) internal view returns (bool success) { + ) internal returns (bool success) { uint256 validationData = _verifyInstallSignatureRaw(replayable, nonce, packages, signature); return Lib4337.checkValidation(validationData); } + function _checkNonce(uint256 nonce) internal virtual returns(bool) { + uint192 key = uint192(nonce >> 64); + uint64 seq = uint64(nonce); + return _moduleStorage().nonce[key]++ == seq; + } + function _verifyInstallSignatureRaw( bool replayable, uint256 nonce, Install[] calldata packages, bytes calldata signature - ) internal view returns (uint256 validationData) { + ) internal returns (uint256 validationData) { ValidationId vId = _validationStorage().root; function(bytes32) internal view returns(bytes32) hashTypedData = replayable ? _hashTypedDataSansChainId : _hashTypedData; + _checkNonce(nonce); bytes32 digest = hashTypedData( keccak256( abi.encode( @@ -164,4 +173,93 @@ abstract contract ModuleManager is ValidationManager, ExecutorManager, HookManag ); return _verifySignature(vId, address(this), digest, signature); } + + struct InstallAndExecute{ + bool replayable; + uint256 nonce; + Install[] packages; + bytes signature; + } + + // NOTE : heavily motivated by solady's erc7821 + function _verifyExecutionData( + bytes32 mode, + bytes calldata executionData + ) internal returns(bool success) { + uint256 id = _executionModeId(mode); + if(id < 2) { + return true; + } + bytes calldata opData; + assembly { + // Use inline assembly to extract the calls and optional `opData` efficiently. + opData.length := 0 + let o := add(executionData.offset, calldataload(executionData.offset)) + // If the offset of `executionData` allows for `opData`, and the mode supports it. + if gt(eq(id, 2), gt(0x40, calldataload(executionData.offset))) { + let q := add(executionData.offset, calldataload(add(0x20, executionData.offset))) + opData.offset := add(q, 0x20) + opData.length := calldataload(q) + } + // Bounds checking for `executionData` is skipped here for efficiency. + // This is safe if it is only used as an argument to `execute` externally. + // If `executionData` used as an argument to other functions externally, + // please perform the bounds checks via `LibERC7579.decodeBatchAndOpData` + /// or `abi.decode` in the other functions for safety. + } + InstallAndExecute calldata exec; + assembly { + exec := opData.offset + } + return _verifyInstallAndExecuteSignature( + mode, + executionData, + exec + ); + } + + // NOTE : heavily motivated by solady's erc7821 + /// @dev 0: invalid mode, 1: no `opData` support, 2: with `opData` support, 3: batch of batches. + function _executionModeId(bytes32 mode) internal view virtual returns (uint256 id) { + // Only supports atomic batched executions. + // For the encoding scheme, see: https://eips.ethereum.org/EIPS/eip-7579 + // Bytes Layout: + // - [0] ( 1 byte ) `0x01` for batch call. + // - [1] ( 1 byte ) `0x00` for revert on any failure. + // - [2..5] ( 4 bytes) Reserved by ERC7579 for future standardization. + // - [6..9] ( 4 bytes) `0x00000000` or `0x78210001` or `0x78210002`. + // - [10..31] (22 bytes) Unused. Free for use. + /// @solidity memory-safe-assembly + assembly { + let m := and(shr(mul(22, 8), mode), 0xffff00000000ffffffff) + id := eq(m, 0x01000000000000000000) // 1. + id := or(shl(1, eq(m, 0x01000000000078210001)), id) // 2. + id := or(mul(3, eq(m, 0x01000000000078210002)), id) // 3. + } + } + + function _verifyInstallAndExecuteSignature( + bytes32 mode, + bytes calldata execData, + InstallAndExecute calldata opData + ) internal returns (bool) { + ValidationId vId = _validationStorage().root; + function(bytes32) internal view returns(bytes32) hashTypedData = + opData.replayable ? _hashTypedDataSansChainId : _hashTypedData; + _checkNonce(opData.nonce); + bytes32 digest = hashTypedData( + keccak256( + abi.encode( + keccak256( + "ExecuteWithInstall(bytes32 mode, bytes execData,uint256 nonce,Install[] packages)Install(uint256 moduleType,address module,bytes moduleData,bytes internalData)" + ), + mode, + execData, + opData.nonce, + _installHash(opData.packages) + ) + ) + ); + return Lib4337.checkValidation(_verifySignature(vId, address(this), digest, opData.signature)); + } } diff --git a/src/core/ValidationManager.sol b/src/core/ValidationManager.sol index d7205fa1..000b7626 100644 --- a/src/core/ValidationManager.sol +++ b/src/core/ValidationManager.sol @@ -231,7 +231,7 @@ abstract contract ValidationManager { if (pkg.moduleType == 1) { vId = ValidationId.wrap(bytes20(pkg.module)); } else if (pkg.moduleType == 5 || pkg.moduleType == 6) { - vId = ValidationId.wrap(bytes20(pkg.internalData[0:4])); + vId = ValidationId.wrap(bytes20(pkg.internalData[0:20])); } else { revert InvalidRootValidation(); } diff --git a/test/Kernel.t.sol b/test/Kernel.t.sol index 5d9cd5c9..843b50f1 100644 --- a/test/Kernel.t.sol +++ b/test/Kernel.t.sol @@ -615,6 +615,59 @@ contract KernelTest is Test { assertEq(address(kernel.executorConfig(newEx).hook), address(0)); } + function test_install_packages_with_signature() external unitTest { + Install[] memory packages = new Install[](2); + packages[0] = Install({ + moduleType : 1, + module : address(newValidator), + internalData: hex"", + moduleData: hex"" + }); + packages[1] = Install({ + moduleType : 5, + module : address(policy), + internalData: abi.encodePacked(permissionId), + moduleData: hex"" + }); + kernel.installModule(false, 0, packages, enableSig(0, true, false, packages, _rootSignHash)); + } + + function test_change_root() external unitTest { + Install[] memory packages = new Install[](2); + packages[0] = Install({ + moduleType : 1, + module : address(newValidator), + internalData: hex"", + moduleData: hex"" + }); + packages[1] = Install({ + moduleType : 5, + module : address(policy), + internalData: abi.encodePacked(permissionId), + moduleData: hex"" + }); + kernel.installModule(false, 0, packages, enableSig(0, true, false, packages, _rootSignHash)); + + kernel.setRoot(ValidationId.wrap(bytes20(address(newValidator)))); + } + + function test_upgradeTo() external unitTest { + Kernel newTemplate = new Kernel(ep); + kernel.upgradeToAndCall(address(newTemplate), hex""); + } + + function test_install_invalid() external unitTest { + MockHook mockHook = new MockHook(); + vm.expectRevert(NotImplemented.selector); + kernel.installModule(10, address(mockHook), abi.encode(hex"", "")); + } + + function test_uninstall_invalid() external unitTest { + MockHook mockHook = new MockHook(); + vm.expectRevert(NotImplemented.selector); + kernel.uninstallModule(10, address(mockHook), abi.encode(hex"", "")); + } + function test_install_hook() external unitTest { MockHook mockHook = new MockHook(); kernel.installModule(4, address(mockHook), abi.encode(hex"", "")); From 44c35f6b45accbc10895f11a25f8eec9eff5bb79 Mon Sep 17 00:00:00 2001 From: leekt Date: Wed, 28 May 2025 03:16:47 +0900 Subject: [PATCH 018/121] instalAndExecute --- src/Kernel.sol | 1 - src/KernelFactory.sol | 31 +++++----- src/KernelHelper.sol | 25 ++++++++ src/core/ModuleManager.sol | 24 ++++--- src/types/Structs.sol | 13 ++++ src/types/Types.sol | 2 +- test/Kernel.t.sol | 124 +++++++++++++++++++++++++++---------- 7 files changed, 157 insertions(+), 63 deletions(-) diff --git a/src/Kernel.sol b/src/Kernel.sol index 477357ca..2de56317 100644 --- a/src/Kernel.sol +++ b/src/Kernel.sol @@ -14,7 +14,6 @@ import "./types/Error.sol"; import "./types/Events.sol"; import "./types/Constants.sol"; -import "forge-std/console.sol"; contract Kernel is ModuleManager, ExecutionManager, UUPSUpgradeable { IEntryPoint immutable entryPoint; diff --git a/src/KernelFactory.sol b/src/KernelFactory.sol index 912a8382..21bd358c 100644 --- a/src/KernelFactory.sol +++ b/src/KernelFactory.sol @@ -22,21 +22,18 @@ contract KernelFactory { return k; } - // function deployWithAdditionalPackage( - // Install[] calldata initialPackages, - // uint256 nonce, - // bool replayable, - // uint256 packageNonce, - // Install[] calldata packages, - // bytes calldata signature - // ) external payable returns (Kernel) { - // bytes32 salt = keccak256(abi.encode(initialPackages, nonce)); - // (bool deployed, address account) = LibClone.createDeterministicERC1967(msg.value, address(template), salt); - // Kernel k = Kernel(payable(account)); - // if(!deployed) { - // k.installModule(true, 0, initialPackages, hex""); - // } - // k.installModule(replayable, packageNonce, packages, signature); - // return k; - // } + function deployWithCall( + Install[] calldata initialPackages, + uint256 nonce, + bytes calldata extraCall + ) external payable returns (Kernel) { + bytes32 salt = keccak256(abi.encode(initialPackages, nonce)); + (bool deployed, address account) = LibClone.createDeterministicERC1967(msg.value, address(template), salt); + Kernel k = Kernel(payable(account)); + if(!deployed) { + k.installModule(true, 0, initialPackages, hex""); + } + address(k).call(extraCall); + return k; + } } diff --git a/src/KernelHelper.sol b/src/KernelHelper.sol index 3a3ba281..4e527281 100644 --- a/src/KernelHelper.sol +++ b/src/KernelHelper.sol @@ -33,6 +33,31 @@ contract KernelHelper { ) ); } + + function installAndExecuteDigest( + address kernel, + bytes32 mode, + Call[] calldata calls, + InstallAndExecute calldata opData + ) external returns (bytes32) { + function(address, bytes32) internal view returns(bytes32) hashTypedData = + opData.replayable ? _hashTypedDataSansChainId : _hashTypedData; + bytes32 digest = hashTypedData( + kernel, + keccak256( + abi.encode( + keccak256( + "ExecuteWithInstall(bytes32 mode, bytes execData,uint256 nonce,Install[] packages)Install(uint256 moduleType,address module,bytes moduleData,bytes internalData)" + ), + mode, + keccak256(abi.encode(calls)), + opData.nonce, + _installHash(opData.packages) + ) + ) + ); + return digest; + } function _installHash(Install[] calldata packages) internal pure returns (bytes32) { bytes32[] memory packageHashes = new bytes32[](packages.length); diff --git a/src/core/ModuleManager.sol b/src/core/ModuleManager.sol index 7d00e74b..16600202 100644 --- a/src/core/ModuleManager.sol +++ b/src/core/ModuleManager.sol @@ -174,13 +174,6 @@ abstract contract ModuleManager is ValidationManager, ExecutorManager, HookManag return _verifySignature(vId, address(this), digest, signature); } - struct InstallAndExecute{ - bool replayable; - uint256 nonce; - Install[] packages; - bytes signature; - } - // NOTE : heavily motivated by solady's erc7821 function _verifyExecutionData( bytes32 mode, @@ -191,10 +184,13 @@ abstract contract ModuleManager is ValidationManager, ExecutorManager, HookManag return true; } bytes calldata opData; + Call[] calldata calls; assembly { // Use inline assembly to extract the calls and optional `opData` efficiently. opData.length := 0 let o := add(executionData.offset, calldataload(executionData.offset)) + calls.offset := add(o, 0x20) + calls.length := calldataload(o) // If the offset of `executionData` allows for `opData`, and the mode supports it. if gt(eq(id, 2), gt(0x40, calldataload(executionData.offset))) { let q := add(executionData.offset, calldataload(add(0x20, executionData.offset))) @@ -211,15 +207,18 @@ abstract contract ModuleManager is ValidationManager, ExecutorManager, HookManag assembly { exec := opData.offset } - return _verifyInstallAndExecuteSignature( + + success = _verifyInstallAndExecuteSignature( mode, - executionData, + calls, exec ); + + _install(exec.packages); } // NOTE : heavily motivated by solady's erc7821 - /// @dev 0: invalid mode, 1: no `opData` support, 2: with `opData` support, 3: batch of batches. + /// @dev 0: invalid mode, 1: no `opData` support, 2: with `opData` support function _executionModeId(bytes32 mode) internal view virtual returns (uint256 id) { // Only supports atomic batched executions. // For the encoding scheme, see: https://eips.ethereum.org/EIPS/eip-7579 @@ -234,13 +233,12 @@ abstract contract ModuleManager is ValidationManager, ExecutorManager, HookManag let m := and(shr(mul(22, 8), mode), 0xffff00000000ffffffff) id := eq(m, 0x01000000000000000000) // 1. id := or(shl(1, eq(m, 0x01000000000078210001)), id) // 2. - id := or(mul(3, eq(m, 0x01000000000078210002)), id) // 3. } } function _verifyInstallAndExecuteSignature( bytes32 mode, - bytes calldata execData, + Call[] calldata calls, InstallAndExecute calldata opData ) internal returns (bool) { ValidationId vId = _validationStorage().root; @@ -254,7 +252,7 @@ abstract contract ModuleManager is ValidationManager, ExecutorManager, HookManag "ExecuteWithInstall(bytes32 mode, bytes execData,uint256 nonce,Install[] packages)Install(uint256 moduleType,address module,bytes moduleData,bytes internalData)" ), mode, - execData, + keccak256(abi.encode(calls)), opData.nonce, _installHash(opData.packages) ) diff --git a/src/types/Structs.sol b/src/types/Structs.sol index 443b7045..bf2980c2 100644 --- a/src/types/Structs.sol +++ b/src/types/Structs.sol @@ -25,3 +25,16 @@ struct ValidationStorage { ValidationId root; mapping(ValidationId vId => ValidationInfo) vInfo; } + +struct Call { + address to; + uint256 value; + bytes data; +} +struct InstallAndExecute{ + bool replayable; + uint256 nonce; + Install[] packages; + bytes signature; +} + diff --git a/src/types/Types.sol b/src/types/Types.sol index 596c9530..762155cb 100644 --- a/src/types/Types.sol +++ b/src/types/Types.sol @@ -67,7 +67,7 @@ function vTypeEqual(ValidationType a, ValidationType b) pure returns (bool) { function isEnable(ValidationMode vMode) pure returns (bool enable) { assembly { - enable := iszero(iszero(and(vMode, 0x800000000000000000000000000000000000000000000000000000000000000))) + enable := iszero(iszero(and(vMode, 0x800000000000000000000000000000000000000000000000000000000000000))) } } diff --git a/test/Kernel.t.sol b/test/Kernel.t.sol index 843b50f1..fd63aa92 100644 --- a/test/Kernel.t.sol +++ b/test/Kernel.t.sol @@ -48,12 +48,6 @@ contract MockCallee { } } -struct Call { - address target; - uint256 value; - bytes data; -} - contract MockContractETH { function useTransfer(address payable recipient, uint256 v) external { recipient.transfer(v); @@ -123,7 +117,7 @@ contract KernelTest is Test { vm.stopPrank(); } - function _rootSignUserOp(PackedUserOperation memory op, bool success) internal returns (bytes memory sig) { + function _rootSignUserOp(PackedUserOperation memory op, bool success, bool replay) internal returns (bytes memory sig) { mockValidator.sudoSetSuccess(success); return hex""; } @@ -135,7 +129,7 @@ contract KernelTest is Test { return hex""; } - function _validatorSignUserOp(PackedUserOperation memory op, bool success) internal returns (bytes memory sig) { + function _validatorSignUserOp(PackedUserOperation memory op, bool success, bool replay) internal returns (bytes memory sig) { newValidator.sudoSetSuccess(success); return hex""; } @@ -147,7 +141,7 @@ contract KernelTest is Test { return hex""; } - function _permissionSignUserOp(PackedUserOperation memory op, bool success) internal returns (bytes memory sig) { + function _permissionSignUserOp(PackedUserOperation memory op, bool success, bool replay) internal returns (bytes memory sig) { bytes[] memory signatures = new bytes[](2); signatures[0] = hex"dead"; signatures[1] = hex"beef"; @@ -219,7 +213,7 @@ contract KernelTest is Test { returns (uint256 nonce) { uint8 uMode = 0; - if (replayableEnable) { + if (replayableUserOp) { uMode += 2 ** 6; } if (enableFlag) { @@ -228,6 +222,7 @@ contract KernelTest is Test { if (replayableEnable) { uMode += 2 ** 2; } + ValidationMode vMode = ValidationMode.wrap(bytes1(uMode)); uint192 key = uint192(bytes24(abi.encodePacked(uMode, vType, vId, bytes2(0x00)))); return ep.getNonce(address(kernel), key); } @@ -326,7 +321,27 @@ contract KernelTest is Test { paymasterAndData: hex"", signature: hex"" }); - ops[0].signature = _rootSignUserOp(ops[0], true); + ops[0].signature = _rootSignUserOp(ops[0], true, false); + ep.handleOps(ops, beneficiary); + assertEq(callee.bar(), 1); + } + + function test_userop_root_replayable() external entryPointTest { + PackedUserOperation[] memory ops = new PackedUserOperation[](1); + ops[0] = PackedUserOperation({ + sender: address(kernel), + nonce: encodeNonce(true, false, false, bytes1(0), bytes20(0)), + initCode: hex"", + callData: abi.encodeWithSelector( + Kernel.execute.selector, bytes32(0), abi.encodePacked(address(callee), uint256(0), MockCallee.foo.selector) + ), + accountGasLimits: bytes32(abi.encodePacked(uint128(1000000), uint128(1000000))), // TODO make this dynamic + preVerificationGas: 1000000, + gasFees: bytes32(abi.encodePacked(uint128(1), uint128(1))), + paymasterAndData: hex"", + signature: hex"" + }); + ops[0].signature = _rootSignUserOp(ops[0], true, true); ep.handleOps(ops, beneficiary); assertEq(callee.bar(), 1); } @@ -346,7 +361,7 @@ contract KernelTest is Test { paymasterAndData: hex"", signature: hex"" }); - ops[0].signature = _rootSignUserOp(ops[0], false); + ops[0].signature = _rootSignUserOp(ops[0], false, false); vm.expectRevert(abi.encodeWithSelector(IEntryPoint.FailedOp.selector, 0, "AA24 signature error")); ep.handleOps(ops, beneficiary); } @@ -366,7 +381,7 @@ contract KernelTest is Test { paymasterAndData: hex"", signature: hex"" }); - ops[0].signature = _validatorSignUserOp(ops[0], true); + ops[0].signature = _validatorSignUserOp(ops[0], true, false); vm.expectRevert(abi.encodeWithSelector(IEntryPoint.FailedOp.selector, 0, "AA24 signature error")); ep.handleOps(ops, beneficiary); } @@ -386,7 +401,7 @@ contract KernelTest is Test { paymasterAndData: hex"", signature: hex"" }); - ops[0].signature = _rootSignUserOp(ops[0], true); + ops[0].signature = _rootSignUserOp(ops[0], true, false); ep.handleOps(ops, beneficiary); assertEq(callee.bar(), 1); } @@ -407,7 +422,7 @@ contract KernelTest is Test { signature: hex"" }); ops[0].signature = - encodeEnableValidatorSignature(0, true, false, _rootSignHash, _validatorSignUserOp(ops[0], true)); + encodeEnableValidatorSignature(0, true, false, _rootSignHash, _validatorSignUserOp(ops[0], true, false)); ep.handleOps(ops, beneficiary); assertEq(callee.bar(), 1); } @@ -428,7 +443,7 @@ contract KernelTest is Test { signature: hex"" }); ops[0].signature = - encodeEnableValidatorSignature(0, false, false, _rootSignHash, _validatorSignUserOp(ops[0], true)); + encodeEnableValidatorSignature(0, false, false, _rootSignHash, _validatorSignUserOp(ops[0], true, false)); vm.expectRevert(abi.encodeWithSelector(IEntryPoint.FailedOp.selector, 0, "AA24 signature error")); ep.handleOps(ops, beneficiary); } @@ -450,7 +465,7 @@ contract KernelTest is Test { }); ops[0].signature = - encodeEnableValidatorSignature(0, true, false, _rootSignHash, _validatorSignUserOp(ops[0], false)); + encodeEnableValidatorSignature(0, true, false, _rootSignHash, _validatorSignUserOp(ops[0], false, false)); vm.expectRevert(abi.encodeWithSelector(IEntryPoint.FailedOp.selector, 0, "AA24 signature error")); ep.handleOps(ops, beneficiary); } @@ -470,7 +485,7 @@ contract KernelTest is Test { paymasterAndData: hex"", signature: hex"" }); - ops[0].signature = _permissionSignUserOp(ops[0], true); + ops[0].signature = _permissionSignUserOp(ops[0], true, false); vm.expectRevert(abi.encodeWithSelector(IEntryPoint.FailedOp.selector, 0, "AA24 signature error")); ep.handleOps(ops, beneficiary); } @@ -490,7 +505,7 @@ contract KernelTest is Test { paymasterAndData: hex"", signature: hex"" }); - ops[0].signature = _rootSignUserOp(ops[0], true); + ops[0].signature = _rootSignUserOp(ops[0], true, false); ep.handleOps(ops, beneficiary); assertEq(callee.bar(), 1); } @@ -512,7 +527,7 @@ contract KernelTest is Test { }); ops[0].signature = - encodeEnablePermissionSignature(0, true, false, _rootSignHash, _permissionSignUserOp(ops[0], true)); + encodeEnablePermissionSignature(0, true, false, _rootSignHash, _permissionSignUserOp(ops[0], true, false)); ep.handleOps(ops, beneficiary); assertEq(callee.bar(), 1); } @@ -533,7 +548,7 @@ contract KernelTest is Test { signature: hex"" }); ops[0].signature = - encodeEnablePermissionSignature(0, false, false, _rootSignHash, _permissionSignUserOp(ops[0], true)); + encodeEnablePermissionSignature(0, false, false, _rootSignHash, _permissionSignUserOp(ops[0], true, false)); vm.expectRevert(abi.encodeWithSelector(IEntryPoint.FailedOp.selector, 0, "AA24 signature error")); ep.handleOps(ops, beneficiary); } @@ -554,7 +569,7 @@ contract KernelTest is Test { signature: hex"" }); ops[0].signature = - encodeEnablePermissionSignature(0, true, false, _rootSignHash, _permissionSignUserOp(ops[0], false)); + encodeEnablePermissionSignature(0, true, false, _rootSignHash, _permissionSignUserOp(ops[0], false, false)); vm.expectRevert(abi.encodeWithSelector(IEntryPoint.FailedOp.selector, 0, "AA24 signature error")); ep.handleOps(ops, beneficiary); } @@ -576,7 +591,7 @@ contract KernelTest is Test { }); permissionRevertIndex = 1; ops[0].signature = - encodeEnablePermissionSignature(0, true, false, _rootSignHash, _permissionSignUserOp(ops[0], false)); + encodeEnablePermissionSignature(0, true, false, _rootSignHash, _permissionSignUserOp(ops[0], false, false)); vm.expectRevert(abi.encodeWithSelector(IEntryPoint.FailedOp.selector, 0, "AA24 signature error")); ep.handleOps(ops, beneficiary); } @@ -899,8 +914,8 @@ contract KernelTest is Test { function test_execute_batch() external unitTest { Call[] memory calls = new Call[](2); - calls[0] = Call({target: address(callee), value: 0, data: abi.encodeWithSelector(MockCallee.foo.selector)}); - calls[1] = Call({target: address(callee), value: 0, data: abi.encodeWithSelector(MockCallee.lorem.selector)}); + calls[0] = Call({to: address(callee), value: 0, data: abi.encodeWithSelector(MockCallee.foo.selector)}); + calls[1] = Call({to: address(callee), value: 0, data: abi.encodeWithSelector(MockCallee.lorem.selector)}); assertEq(callee.data(), ""); vm.expectEmit(address(callee)); emit MockCallee.Lorem(); @@ -911,9 +926,9 @@ contract KernelTest is Test { function test_execute_batch_fail() external unitTest { Call[] memory calls = new Call[](2); - calls[0] = Call({target: address(callee), value: 0, data: abi.encodeWithSelector(MockCallee.foo.selector)}); + calls[0] = Call({to: address(callee), value: 0, data: abi.encodeWithSelector(MockCallee.foo.selector)}); calls[1] = - Call({target: address(callee), value: 0, data: abi.encodeWithSelector(MockCallee.forceRevert.selector)}); + Call({to: address(callee), value: 0, data: abi.encodeWithSelector(MockCallee.forceRevert.selector)}); assertEq(callee.data(), ""); vm.expectRevert(MockCallee.Haha.selector); kernel.execute(LibERC7579.encodeMode(bytes1(0x01), bytes1(0x00), bytes4(0), bytes22(0)), abi.encode(calls)); @@ -921,9 +936,9 @@ contract KernelTest is Test { function test_execute_batch_fail_try() external unitTest { Call[] memory calls = new Call[](2); - calls[0] = Call({target: address(callee), value: 0, data: abi.encodeWithSelector(MockCallee.foo.selector)}); + calls[0] = Call({to: address(callee), value: 0, data: abi.encodeWithSelector(MockCallee.foo.selector)}); calls[1] = - Call({target: address(callee), value: 0, data: abi.encodeWithSelector(MockCallee.forceRevert.selector)}); + Call({to: address(callee), value: 0, data: abi.encodeWithSelector(MockCallee.forceRevert.selector)}); assertEq(callee.data(), ""); kernel.execute(LibERC7579.encodeMode(bytes1(0x01), bytes1(0x01), bytes4(0), bytes22(0)), abi.encode(calls)); assertEq(callee.bar(), 1); @@ -964,8 +979,8 @@ contract KernelTest is Test { function test_execute_batch_from_executor() external unitTestExecutor { Call[] memory calls = new Call[](2); - calls[0] = Call({target: address(callee), value: 0, data: abi.encodeWithSelector(MockCallee.foo.selector)}); - calls[1] = Call({target: address(callee), value: 0, data: abi.encodeWithSelector(MockCallee.lorem.selector)}); + calls[0] = Call({to: address(callee), value: 0, data: abi.encodeWithSelector(MockCallee.foo.selector)}); + calls[1] = Call({to: address(callee), value: 0, data: abi.encodeWithSelector(MockCallee.lorem.selector)}); assertEq(callee.data(), ""); vm.expectEmit(address(callee)); emit MockCallee.Lorem(); @@ -976,6 +991,53 @@ contract KernelTest is Test { assertEq(callee.data(), "lorem ipsum"); } + bytes32 constant MODE_EXECUTE_WITH_OP_DATA = bytes10(0x01000000000078210001); + function encodeInstallWithExecute(Call[] memory calls, bool replayable, uint256 nonce, Install[] memory packages) internal returns(bytes memory sig) { + InstallAndExecute memory ie = InstallAndExecute({ + replayable : replayable, + nonce : nonce, + packages : packages, + signature : hex"" + }); + bytes32 hash = helper.installAndExecuteDigest(address(kernel), MODE_EXECUTE_WITH_OP_DATA, calls, ie); + console.log("Hello ??"); + sig = abi.encode( + false, + uint256(0), + packages, + _rootSignHash(hash, true) + ); + } + + function test_execute_batch_from_executor_with_install_data() external { + address newExecutor = makeAddr("New Executor"); + Install[] memory packages = new Install[](1); + packages[0] = Install({ + moduleType : 2, + module : newExecutor, + internalData : hex"", + moduleData : hex"" + }); + + Call[] memory calls = new Call[](2); + calls[0] = Call({to: address(callee), value: 0, data: abi.encodeWithSelector(MockCallee.foo.selector)}); + calls[1] = Call({to: address(callee), value: 0, data: abi.encodeWithSelector(MockCallee.lorem.selector)}); + assertEq(callee.data(), ""); + vm.startPrank(newExecutor); + //vm.expectEmit(address(callee)); + //emit MockCallee.Lorem(); + kernel.executeFromExecutor( + MODE_EXECUTE_WITH_OP_DATA, + abi.encode( + calls, + encodeInstallWithExecute(calls, false, uint256(0), packages) + ) + ); + assertEq(callee.bar(), 1); + assertEq(callee.data(), "lorem ipsum"); + vm.stopPrank(); + } + function test_execute_delegatecall_from_executor() external unitTestExecutor { vm.expectEmit(address(kernel)); emit MockCallee.Lorem(); From 3f8acd8e6c9369abae701465db6797ad8eebfb90 Mon Sep 17 00:00:00 2001 From: leekt Date: Wed, 28 May 2025 03:18:36 +0900 Subject: [PATCH 019/121] install and execute --- test/Kernel.t.sol | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/test/Kernel.t.sol b/test/Kernel.t.sol index fd63aa92..91a4e276 100644 --- a/test/Kernel.t.sol +++ b/test/Kernel.t.sol @@ -228,6 +228,7 @@ contract KernelTest is Test { } function test_codesize() external { + vm.skip(true); address implementation = address(factory.template()); console.log("Code size :", implementation.code.length); require(implementation.code.length <= 24576, "Code too big"); @@ -1000,7 +1001,6 @@ contract KernelTest is Test { signature : hex"" }); bytes32 hash = helper.installAndExecuteDigest(address(kernel), MODE_EXECUTE_WITH_OP_DATA, calls, ie); - console.log("Hello ??"); sig = abi.encode( false, uint256(0), @@ -1024,13 +1024,14 @@ contract KernelTest is Test { calls[1] = Call({to: address(callee), value: 0, data: abi.encodeWithSelector(MockCallee.lorem.selector)}); assertEq(callee.data(), ""); vm.startPrank(newExecutor); - //vm.expectEmit(address(callee)); - //emit MockCallee.Lorem(); + bytes memory installData = encodeInstallWithExecute(calls, false, uint256(0), packages); + vm.expectEmit(address(callee)); + emit MockCallee.Lorem(); kernel.executeFromExecutor( MODE_EXECUTE_WITH_OP_DATA, abi.encode( calls, - encodeInstallWithExecute(calls, false, uint256(0), packages) + installData ) ); assertEq(callee.bar(), 1); From 5b6bf04653cebde4d3e6041f6816361c5d40e70e Mon Sep 17 00:00:00 2001 From: leekt Date: Wed, 28 May 2025 03:57:28 +0900 Subject: [PATCH 020/121] test done with factory, todo:7702 and ecdsa --- src/Kernel.sol | 8 +- src/KernelFactory.sol | 15 ++-- src/KernelHelper.sol | 2 +- src/core/ModuleManager.sol | 39 ++++----- src/core/ValidationManager.sol | 16 ++-- src/lib/Lib4337.sol | 4 +- src/types/Error.sol | 1 + src/types/Structs.sol | 4 +- src/types/Types.sol | 2 +- test/Kernel.t.sol | 152 ++++++++++++++++++++++----------- 10 files changed, 148 insertions(+), 95 deletions(-) diff --git a/src/Kernel.sol b/src/Kernel.sol index 2de56317..8074ac41 100644 --- a/src/Kernel.sol +++ b/src/Kernel.sol @@ -14,7 +14,6 @@ import "./types/Error.sol"; import "./types/Events.sol"; import "./types/Constants.sol"; - contract Kernel is ModuleManager, ExecutionManager, UUPSUpgradeable { IEntryPoint immutable entryPoint; @@ -89,7 +88,12 @@ contract Kernel is ModuleManager, ExecutionManager, UUPSUpgradeable { Lib4337.intersectValidationData(validationData, validateUserOpFn(vId, opHash, userOp, signature)); } - function _erc1271IsValidSignatureNowCalldata(bytes32 hash, bytes calldata signature) internal view override returns(bool) { + function _erc1271IsValidSignatureNowCalldata(bytes32 hash, bytes calldata signature) + internal + view + override + returns (bool) + { ValidationId vId = ValidationId.wrap(bytes20(signature[0:20])); uint256 validationData = _verifySignature(vId, msg.sender, hash, signature[20:]); return Lib4337.checkValidation(validationData); diff --git a/src/KernelFactory.sol b/src/KernelFactory.sol index 21bd358c..115b77b8 100644 --- a/src/KernelFactory.sol +++ b/src/KernelFactory.sol @@ -22,18 +22,19 @@ contract KernelFactory { return k; } - function deployWithCall( - Install[] calldata initialPackages, - uint256 nonce, - bytes calldata extraCall - ) external payable returns (Kernel) { + function deployWithCall(Install[] calldata initialPackages, uint256 nonce, bytes calldata extraCall) + external + payable + returns (Kernel) + { bytes32 salt = keccak256(abi.encode(initialPackages, nonce)); (bool deployed, address account) = LibClone.createDeterministicERC1967(msg.value, address(template), salt); Kernel k = Kernel(payable(account)); - if(!deployed) { + if (!deployed) { k.installModule(true, 0, initialPackages, hex""); } - address(k).call(extraCall); + (bool success, ) = address(k).call(extraCall); + require(success, "call failed"); return k; } } diff --git a/src/KernelHelper.sol b/src/KernelHelper.sol index 4e527281..78c1985b 100644 --- a/src/KernelHelper.sol +++ b/src/KernelHelper.sol @@ -33,7 +33,7 @@ contract KernelHelper { ) ); } - + function installAndExecuteDigest( address kernel, bytes32 mode, diff --git a/src/core/ModuleManager.sol b/src/core/ModuleManager.sol index 16600202..e6248eac 100644 --- a/src/core/ModuleManager.sol +++ b/src/core/ModuleManager.sol @@ -48,7 +48,9 @@ abstract contract ModuleManager is ValidationManager, ExecutorManager, HookManag for (uint256 i = 0; i < packages.length; i++) { Install calldata pkg = packages[i]; packageHashes[i] = keccak256( - abi.encode(pkg.moduleType, pkg.module, calldataKeccak(pkg.moduleData), calldataKeccak(pkg.internalData)) + abi.encode( + pkg.moduleType, pkg.module, calldataKeccak(pkg.moduleData), calldataKeccak(pkg.internalData) + ) ); } } @@ -133,7 +135,6 @@ abstract contract ModuleManager is ValidationManager, ExecutorManager, HookManag hook(module, internalData, success); } - function _verifyInstallSignature( bool replayable, uint256 nonce, @@ -144,7 +145,7 @@ abstract contract ModuleManager is ValidationManager, ExecutorManager, HookManag return Lib4337.checkValidation(validationData); } - function _checkNonce(uint256 nonce) internal virtual returns(bool) { + function _checkNonce(uint256 nonce) internal virtual returns (bool) { uint192 key = uint192(nonce >> 64); uint64 seq = uint64(nonce); return _moduleStorage().nonce[key]++ == seq; @@ -159,7 +160,7 @@ abstract contract ModuleManager is ValidationManager, ExecutorManager, HookManag ValidationId vId = _validationStorage().root; function(bytes32) internal view returns(bytes32) hashTypedData = replayable ? _hashTypedDataSansChainId : _hashTypedData; - _checkNonce(nonce); + require(_checkNonce(nonce), InvalidNonce()); bytes32 digest = hashTypedData( keccak256( abi.encode( @@ -175,12 +176,9 @@ abstract contract ModuleManager is ValidationManager, ExecutorManager, HookManag } // NOTE : heavily motivated by solady's erc7821 - function _verifyExecutionData( - bytes32 mode, - bytes calldata executionData - ) internal returns(bool success) { + function _verifyExecutionData(bytes32 mode, bytes calldata executionData) internal returns (bool success) { uint256 id = _executionModeId(mode); - if(id < 2) { + if (id < 2) { return true; } bytes calldata opData; @@ -207,16 +205,12 @@ abstract contract ModuleManager is ValidationManager, ExecutorManager, HookManag assembly { exec := opData.offset } - - success = _verifyInstallAndExecuteSignature( - mode, - calls, - exec - ); + + success = _verifyInstallAndExecuteSignature(mode, calls, exec); _install(exec.packages); } - + // NOTE : heavily motivated by solady's erc7821 /// @dev 0: invalid mode, 1: no `opData` support, 2: with `opData` support function _executionModeId(bytes32 mode) internal view virtual returns (uint256 id) { @@ -235,16 +229,15 @@ abstract contract ModuleManager is ValidationManager, ExecutorManager, HookManag id := or(shl(1, eq(m, 0x01000000000078210001)), id) // 2. } } - - function _verifyInstallAndExecuteSignature( - bytes32 mode, - Call[] calldata calls, - InstallAndExecute calldata opData - ) internal returns (bool) { + + function _verifyInstallAndExecuteSignature(bytes32 mode, Call[] calldata calls, InstallAndExecute calldata opData) + internal + returns (bool) + { ValidationId vId = _validationStorage().root; function(bytes32) internal view returns(bytes32) hashTypedData = opData.replayable ? _hashTypedDataSansChainId : _hashTypedData; - _checkNonce(opData.nonce); + require(_checkNonce(opData.nonce), InvalidNonce()); bytes32 digest = hashTypedData( keccak256( abi.encode( diff --git a/src/core/ValidationManager.sol b/src/core/ValidationManager.sol index 000b7626..64a3900f 100644 --- a/src/core/ValidationManager.sol +++ b/src/core/ValidationManager.sol @@ -91,7 +91,7 @@ abstract contract ValidationManager { require($.policies[$.policies.length - 1] == _policy, InvalidPermissionUninstallOrder()); $.policies.pop(); } - if($.signer == address(0)) { + if ($.signer == address(0)) { $.vType = VALIDATION_TYPE_ROOT; } } @@ -139,17 +139,23 @@ abstract contract ValidationManager { if (ValidationId.unwrap(vId) == bytes20(0)) { return _verify7702Signature(_hash, _signature) ? 0 : 1; } - IValidator validator = IValidator(address(ValidationId.unwrap(vId))); // TODO: add permission support; - validationData = validator.isValidSignatureWithSender(requester, /*NOTE: fix this */ _hash, _signature) + ValidationInfo storage vInfo = _validationStorage().vInfo[vId]; + if(vInfo.vType == VALIDATION_TYPE_VALIDATOR) { + IValidator validator = IValidator(address(ValidationId.unwrap(vId))); // TODO: add permission support; + validationData = validator.isValidSignatureWithSender(requester, /*NOTE: fix this */ _hash, _signature) == ERC1271_MAGICVALUE ? 0 : 1; + } else if(vInfo.vType == VALIDATION_TYPE_PERMISSION) { + return _verifySignaturePermission(vId, vInfo, requester, _hash, _signature); + } else { + return 1; + } } - function _verifySignaturePermission(ValidationId vId, address requester, bytes32 _hash, bytes calldata _signature) + function _verifySignaturePermission(ValidationId vId, ValidationInfo storage vInfo, address requester, bytes32 _hash, bytes calldata _signature) internal view returns (uint256 validationData) { - ValidationInfo storage vInfo = _validationStorage().vInfo[vId]; unchecked { uint256 length = vInfo.policies.length + 1; diff --git a/src/lib/Lib4337.sol b/src/lib/Lib4337.sol index 219804fb..fa280d36 100644 --- a/src/lib/Lib4337.sol +++ b/src/lib/Lib4337.sol @@ -30,8 +30,8 @@ library Lib4337 { } } - function checkValidation(uint256 validationData) external view returns(bool) { - (uint48 vAfter, uint48 vUntil,address res) = Lib4337.parseValidationData(validationData); + function checkValidation(uint256 validationData) external view returns (bool) { + (uint48 vAfter, uint48 vUntil, address res) = Lib4337.parseValidationData(validationData); if (vAfter > block.timestamp || vUntil < block.timestamp) { return false; } diff --git a/src/types/Error.sol b/src/types/Error.sol index eb80e8a8..2db479e3 100644 --- a/src/types/Error.sol +++ b/src/types/Error.sol @@ -25,3 +25,4 @@ error OccupiedValidationId(); error InvalidPermissionUninstallOrder(); error InvalidPermissionId(); +error InvalidNonce(); diff --git a/src/types/Structs.sol b/src/types/Structs.sol index bf2980c2..af60cc9a 100644 --- a/src/types/Structs.sol +++ b/src/types/Structs.sol @@ -31,10 +31,10 @@ struct Call { uint256 value; bytes data; } -struct InstallAndExecute{ + +struct InstallAndExecute { bool replayable; uint256 nonce; Install[] packages; bytes signature; } - diff --git a/src/types/Types.sol b/src/types/Types.sol index 762155cb..596c9530 100644 --- a/src/types/Types.sol +++ b/src/types/Types.sol @@ -67,7 +67,7 @@ function vTypeEqual(ValidationType a, ValidationType b) pure returns (bool) { function isEnable(ValidationMode vMode) pure returns (bool enable) { assembly { - enable := iszero(iszero(and(vMode, 0x800000000000000000000000000000000000000000000000000000000000000))) + enable := iszero(iszero(and(vMode, 0x800000000000000000000000000000000000000000000000000000000000000))) } } diff --git a/test/Kernel.t.sol b/test/Kernel.t.sol index 91a4e276..6aefd714 100644 --- a/test/Kernel.t.sol +++ b/test/Kernel.t.sol @@ -117,7 +117,10 @@ contract KernelTest is Test { vm.stopPrank(); } - function _rootSignUserOp(PackedUserOperation memory op, bool success, bool replay) internal returns (bytes memory sig) { + function _rootSignUserOp(PackedUserOperation memory op, bool success, bool replay) + internal + returns (bytes memory sig) + { mockValidator.sudoSetSuccess(success); return hex""; } @@ -129,7 +132,10 @@ contract KernelTest is Test { return hex""; } - function _validatorSignUserOp(PackedUserOperation memory op, bool success, bool replay) internal returns (bytes memory sig) { + function _validatorSignUserOp(PackedUserOperation memory op, bool success, bool replay) + internal + returns (bytes memory sig) + { newValidator.sudoSetSuccess(success); return hex""; } @@ -141,7 +147,10 @@ contract KernelTest is Test { return hex""; } - function _permissionSignUserOp(PackedUserOperation memory op, bool success, bool replay) internal returns (bytes memory sig) { + function _permissionSignUserOp(PackedUserOperation memory op, bool success, bool replay) + internal + returns (bytes memory sig) + { bytes[] memory signatures = new bytes[](2); signatures[0] = hex"dead"; signatures[1] = hex"beef"; @@ -155,7 +164,15 @@ contract KernelTest is Test { return abi.encode(signatures); } - function _permissionSignHash(bytes32 hash, bool success) internal returns (bytes memory sig) {} + function _permissionSignHash(bytes32 hash, bool success) internal returns (bytes memory sig) { + bytes[] memory signatures = new bytes[](2); + signatures[0] = hex"dead"; + signatures[1] = hex"beef"; + policy.sudoSetPass(address(kernel), permissionId, true); + signer.sudoSetPass(address(kernel), permissionId, true); + + return abi.encode(signatures); + } function enableSig( uint256 nonce, @@ -307,6 +324,33 @@ contract KernelTest is Test { mock.batchMint(address(kernel), ids, amounts, hex"deadbeef"); } + function test_executeuserop_root() external entryPointTest { + PackedUserOperation[] memory ops = new PackedUserOperation[](1); + ops[0] = PackedUserOperation({ + sender: address(kernel), + nonce: encodeNonce(false, false, false, bytes1(0), bytes20(0)), + initCode: hex"", + callData: abi.encodePacked( + Kernel.executeUserOp.selector, + abi.encodeWithSelector( + Kernel.execute.selector, + bytes32(0), + abi.encodePacked(address(callee), uint256(0), MockCallee.foo.selector) + ) + ), + accountGasLimits: bytes32(abi.encodePacked(uint128(1000000), uint128(1000000))), // TODO make this dynamic + preVerificationGas: 1000000, + gasFees: bytes32(abi.encodePacked(uint128(1), uint128(1))), + paymasterAndData: hex"", + signature: hex"" + }); + ops[0].signature = _rootSignUserOp(ops[0], true, false); + vm.startPrank(address(ep)); + kernel.executeUserOp(ops[0], keccak256("hello world")); + vm.stopPrank(); + assertEq(callee.bar(), 1); + } + function test_userop_root() external entryPointTest { PackedUserOperation[] memory ops = new PackedUserOperation[](1); ops[0] = PackedUserOperation({ @@ -603,6 +647,24 @@ contract KernelTest is Test { Kernel k = factory.deploy(pkgs, 1); } + function test_deploy_existing() external { + Install[] memory pkgs = new Install[](1); + pkgs[0] = Install({moduleType: 1, module: address(mockValidator), moduleData: hex"", internalData: hex""}); + Kernel k = factory.deploy(pkgs, 1); + assertEq(address(k), address(factory.deploy(pkgs, 1))); + } + + function test_deploy_with_call() external unitTest { + Install[] memory initPkgs = new Install[](1); + initPkgs[0] = Install({moduleType: 1, module: address(mockValidator), moduleData: hex"", internalData: hex""}); + Install[] memory pkgs = new Install[](1); + pkgs[0] = Install({moduleType: 1, module: address(newValidator), moduleData: hex"", internalData: hex""}); + bytes memory sig = enableSig(0, true, false, pkgs, _rootSignHash); + Kernel k = factory.deployWithCall(initPkgs, 1, abi.encodeWithSelector(0xa706cd33, false, 0, pkgs, sig)); + ValidationInfo memory vInfo = k.validationInfo(ValidationId.wrap(bytes20(address(newValidator)))); + assertTrue(vInfo.vType == VALIDATION_TYPE_VALIDATOR); + } + function test_install_executor_oninstall_success() external unitTest { address newEx = address(new MockExecutor()); kernel.installModule(2, newEx, abi.encode(hex"deadbeef", "")); @@ -633,15 +695,10 @@ contract KernelTest is Test { function test_install_packages_with_signature() external unitTest { Install[] memory packages = new Install[](2); - packages[0] = Install({ - moduleType : 1, - module : address(newValidator), - internalData: hex"", - moduleData: hex"" - }); + packages[0] = Install({moduleType: 1, module: address(newValidator), internalData: hex"", moduleData: hex""}); packages[1] = Install({ - moduleType : 5, - module : address(policy), + moduleType: 5, + module: address(policy), internalData: abi.encodePacked(permissionId), moduleData: hex"" }); @@ -650,15 +707,10 @@ contract KernelTest is Test { function test_change_root() external unitTest { Install[] memory packages = new Install[](2); - packages[0] = Install({ - moduleType : 1, - module : address(newValidator), - internalData: hex"", - moduleData: hex"" - }); + packages[0] = Install({moduleType: 1, module: address(newValidator), internalData: hex"", moduleData: hex""}); packages[1] = Install({ - moduleType : 5, - module : address(policy), + moduleType: 5, + module: address(policy), internalData: abi.encodePacked(permissionId), moduleData: hex"" }); @@ -670,6 +722,8 @@ contract KernelTest is Test { function test_upgradeTo() external unitTest { Kernel newTemplate = new Kernel(ep); kernel.upgradeToAndCall(address(newTemplate), hex""); + bytes32 impl = vm.load(address(kernel), ERC1967_IMPLEMENTATION_SLOT); + assertEq(address(uint160(uint256(impl))), address(newTemplate)); } function test_install_invalid() external unitTest { @@ -700,6 +754,8 @@ contract KernelTest is Test { kernel.installModule(1, address(newValidator), abi.encode(hex"deadbeef", "InternalData")); ValidationInfo memory vInfo = kernel.validationInfo(vId); assertTrue(vInfo.vType == VALIDATION_TYPE_VALIDATOR); + bytes4 ret = kernel.isValidSignature(keccak256("Hello world"), abi.encodePacked(newValidator, _validatorSignHash(keccak256("Hello world"), true))); + assertEq(ret, ERC1271_MAGICVALUE); } function test_uninstall_validator() external unitTest { @@ -712,6 +768,16 @@ contract KernelTest is Test { assertTrue(vInfo.vType == VALIDATION_TYPE_ROOT); } + function test_install_permission() external unitTest { + ValidationId vId = ValidationId.wrap(permissionId); + ValidationInfo memory vInfo = kernel.validationInfo(vId); + assertTrue(vInfo.vType == VALIDATION_TYPE_ROOT); + kernel.installModule(5, address(policy), abi.encode(hex"deadbeef", abi.encodePacked(permissionId))); + kernel.installModule(6, address(signer), abi.encode(hex"deadbeef", abi.encodePacked(permissionId))); + bytes4 ret = kernel.isValidSignature(keccak256("Hello world"), abi.encodePacked(permissionId, _permissionSignHash(keccak256("Hello world"), true))); + assertEq(ret, ERC1271_MAGICVALUE); + } + function test_install_policy() external unitTest { MockPolicy mock = new MockPolicy(); ValidationId vId = ValidationId.wrap(bytes20(keccak256(abi.encodePacked("deadbeef")))); @@ -721,7 +787,7 @@ contract KernelTest is Test { vInfo = kernel.validationInfo(vId); assertTrue(vInfo.vType == VALIDATION_TYPE_PERMISSION); } - + function test_uninstall_policy() external unitTest { MockPolicy mock = new MockPolicy(); ValidationId vId = ValidationId.wrap(bytes20(keccak256(abi.encodePacked("deadbeef")))); @@ -744,7 +810,7 @@ contract KernelTest is Test { vInfo = kernel.validationInfo(vId); assertTrue(vInfo.vType == VALIDATION_TYPE_PERMISSION); } - + function test_uninstall_signer() external unitTest { MockSigner mock = new MockSigner(); ValidationId vId = ValidationId.wrap(bytes20(keccak256(abi.encodePacked("deadbeef")))); @@ -928,8 +994,7 @@ contract KernelTest is Test { function test_execute_batch_fail() external unitTest { Call[] memory calls = new Call[](2); calls[0] = Call({to: address(callee), value: 0, data: abi.encodeWithSelector(MockCallee.foo.selector)}); - calls[1] = - Call({to: address(callee), value: 0, data: abi.encodeWithSelector(MockCallee.forceRevert.selector)}); + calls[1] = Call({to: address(callee), value: 0, data: abi.encodeWithSelector(MockCallee.forceRevert.selector)}); assertEq(callee.data(), ""); vm.expectRevert(MockCallee.Haha.selector); kernel.execute(LibERC7579.encodeMode(bytes1(0x01), bytes1(0x00), bytes4(0), bytes22(0)), abi.encode(calls)); @@ -938,8 +1003,7 @@ contract KernelTest is Test { function test_execute_batch_fail_try() external unitTest { Call[] memory calls = new Call[](2); calls[0] = Call({to: address(callee), value: 0, data: abi.encodeWithSelector(MockCallee.foo.selector)}); - calls[1] = - Call({to: address(callee), value: 0, data: abi.encodeWithSelector(MockCallee.forceRevert.selector)}); + calls[1] = Call({to: address(callee), value: 0, data: abi.encodeWithSelector(MockCallee.forceRevert.selector)}); assertEq(callee.data(), ""); kernel.execute(LibERC7579.encodeMode(bytes1(0x01), bytes1(0x01), bytes4(0), bytes22(0)), abi.encode(calls)); assertEq(callee.bar(), 1); @@ -993,31 +1057,21 @@ contract KernelTest is Test { } bytes32 constant MODE_EXECUTE_WITH_OP_DATA = bytes10(0x01000000000078210001); - function encodeInstallWithExecute(Call[] memory calls, bool replayable, uint256 nonce, Install[] memory packages) internal returns(bytes memory sig) { - InstallAndExecute memory ie = InstallAndExecute({ - replayable : replayable, - nonce : nonce, - packages : packages, - signature : hex"" - }); + + function encodeInstallWithExecute(Call[] memory calls, bool replayable, uint256 nonce, Install[] memory packages) + internal + returns (bytes memory sig) + { + InstallAndExecute memory ie = + InstallAndExecute({replayable: replayable, nonce: nonce, packages: packages, signature: hex""}); bytes32 hash = helper.installAndExecuteDigest(address(kernel), MODE_EXECUTE_WITH_OP_DATA, calls, ie); - sig = abi.encode( - false, - uint256(0), - packages, - _rootSignHash(hash, true) - ); + sig = abi.encode(false, uint256(0), packages, _rootSignHash(hash, true)); } function test_execute_batch_from_executor_with_install_data() external { address newExecutor = makeAddr("New Executor"); Install[] memory packages = new Install[](1); - packages[0] = Install({ - moduleType : 2, - module : newExecutor, - internalData : hex"", - moduleData : hex"" - }); + packages[0] = Install({moduleType: 2, module: newExecutor, internalData: hex"", moduleData: hex""}); Call[] memory calls = new Call[](2); calls[0] = Call({to: address(callee), value: 0, data: abi.encodeWithSelector(MockCallee.foo.selector)}); @@ -1027,13 +1081,7 @@ contract KernelTest is Test { bytes memory installData = encodeInstallWithExecute(calls, false, uint256(0), packages); vm.expectEmit(address(callee)); emit MockCallee.Lorem(); - kernel.executeFromExecutor( - MODE_EXECUTE_WITH_OP_DATA, - abi.encode( - calls, - installData - ) - ); + kernel.executeFromExecutor(MODE_EXECUTE_WITH_OP_DATA, abi.encode(calls, installData)); assertEq(callee.bar(), 1); assertEq(callee.data(), "lorem ipsum"); vm.stopPrank(); From a449911898e0247323bd66358672055370a741e2 Mon Sep 17 00:00:00 2001 From: leekt Date: Wed, 28 May 2025 03:59:23 +0900 Subject: [PATCH 021/121] updated readme to show coverage command --- README.md | 39 +++++++++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index fb796003..50b34cdb 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,14 @@ +# how to run coverage + +```sh +forge coverage --no-match-coverage "(script|test|Foo|Bar|validator|sdk|signer)" --report lcov && genhtml lcov.info --output-directory coverage --ignore-errors inconsistent --ignore-errors corrupt +``` + +and +```sh +open coverage/index.html +``` + ## TODO - Testing - [ ] certora testing @@ -5,18 +16,18 @@ - [ ] halmos testing ## Kernel V4 -- [ ] native v0.8 support - - [ ] factory update, needs to consider 7702 context - - [ ] eip712 userOpHash support +- [x] native v0.8 support + - [x] factory update, needs to consider 7702 context + - [x] eip712 userOpHash support - [ ] native 7702 support -- [ ] 7579 account - - [ ] erc7821 execute interface - - [ ] execute with signature -- [ ] enable mode - - [ ] allow installing modules - - [ ] allow multichain replay signature -- [ ] permission validation method -- [ ] signature replay - - [ ] multichain replay -- [ ] install with signature - + - test +- [x] 7579 account + - [x] erc7821 execute interface + - [x] execute with signature +- [x] enable mode + - [x] allow installing modules + - [x] allow multichain replay signature +- [x] permission validation method +- [x] signature replay + - [x] multichain replay +- [x] install with signature From fb541daf6f01bebfed6e30fe1f9ca8002bc75275 Mon Sep 17 00:00:00 2001 From: leekt Date: Wed, 28 May 2025 04:37:47 +0900 Subject: [PATCH 022/121] erc7579 helper functions done --- src/Kernel.sol | 58 ++++++++++++++++++++++++++++++++++++++++++++++- test/Kernel.t.sol | 48 +++++++++++++++++++++++++++++++++------ 2 files changed, 98 insertions(+), 8 deletions(-) diff --git a/src/Kernel.sol b/src/Kernel.sol index 8074ac41..0c64d321 100644 --- a/src/Kernel.sol +++ b/src/Kernel.sol @@ -3,16 +3,18 @@ pragma solidity ^0.8.0; import {IEntryPoint} from "account-abstraction/interfaces/IEntryPoint.sol"; import {IAccount} from "account-abstraction/interfaces/IAccount.sol"; import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; -import {IValidator} from "./interfaces/IERC7579Modules.sol"; +import {IValidator, IExecutor} from "./interfaces/IERC7579Modules.sol"; import {ModuleManager, Install} from "./core/ModuleManager.sol"; import {parseNonce} from "./core/ValidationManager.sol"; import {ExecutionManager} from "./core/ExecutionManager.sol"; import {Lib4337} from "./lib/Lib4337.sol"; import {UUPSUpgradeable} from "solady/utils/UUPSUpgradeable.sol"; +import {LibERC7579} from "solady/accounts/LibERC7579.sol"; import "./types/Types.sol"; import "./types/Error.sol"; import "./types/Events.sol"; import "./types/Constants.sol"; +import "./types/Structs.sol"; contract Kernel is ModuleManager, ExecutionManager, UUPSUpgradeable { IEntryPoint immutable entryPoint; @@ -215,4 +217,58 @@ contract Kernel is ModuleManager, ExecutionManager, UUPSUpgradeable { receive() external payable { emit Received(msg.sender, msg.value); } + + function supportsExecutionMode(bytes32 mode) external view returns(bool) { + bytes1 callType = LibERC7579.getCallType(mode); + bytes1 execType = LibERC7579.getExecType(mode); + if (execType == LibERC7579.EXECTYPE_DEFAULT) { + } else if (execType == LibERC7579.EXECTYPE_TRY) { + } else { + return false; + } + if (callType == LibERC7579.CALLTYPE_SINGLE) { + } else if (callType == LibERC7579.CALLTYPE_BATCH) { + } else if (callType == LibERC7579.CALLTYPE_DELEGATECALL) { + } else { + return false; + } + return true; + } + + function supportsModule(uint256 moduleTypeId) external view returns(bool) { + return moduleTypeId < 7; + } + + function isModuleInstalled(uint256 moduleTypeId, address module, bytes calldata additionalContext) external view returns(bool) { + if(moduleTypeId == 1) { + ValidationId vId = ValidationId.wrap(bytes20(module)); + return !(_validationStorage().vInfo[vId].vType == VALIDATION_TYPE_ROOT); + } else if(moduleTypeId == 2) { + return address(_executorConfig(IExecutor(module)).hook) != address(0); + } else if(moduleTypeId == 3) { + bytes4 selector = bytes4(additionalContext); + return _selectorConfig(selector).target == module; + } else if(moduleTypeId == 4) { + return _hookStorage().enabled[module]; + } else if(moduleTypeId == 5) { + ValidationId vId = ValidationId.wrap(bytes20(additionalContext)); + ValidationInfo storage $ =_validationStorage().vInfo[vId]; + for(uint256 i = 0; i < $.policies.length; i++) { + if($.policies[i] == module) { + return true; + } + } + return false; + } else if(moduleTypeId == 6) { + ValidationId vId = ValidationId.wrap(bytes20(additionalContext)); + ValidationInfo storage $ =_validationStorage().vInfo[vId]; + return $.signer == module; + } else { + revert NotImplemented(); + } + } + + function accountId() external view returns (string memory accountImplementationId) { + return "kernel.v0.4"; + } } diff --git a/test/Kernel.t.sol b/test/Kernel.t.sol index 6aefd714..af2b0c47 100644 --- a/test/Kernel.t.sol +++ b/test/Kernel.t.sol @@ -666,15 +666,18 @@ contract KernelTest is Test { } function test_install_executor_oninstall_success() external unitTest { + assertTrue(kernel.supportsModule(2)); address newEx = address(new MockExecutor()); kernel.installModule(2, newEx, abi.encode(hex"deadbeef", "")); assertEq(address(kernel.executorConfig(newEx).hook), address(1)); + assertTrue(kernel.isModuleInstalled(2, newEx, hex"")); } function test_install_executor_oninstall_fail() external unitTest { address newEx = makeAddr("New Executor"); kernel.installModule(2, newEx, abi.encode(hex"", "")); assertEq(address(kernel.executorConfig(newEx).hook), address(1)); + assertTrue(kernel.isModuleInstalled(2, newEx, hex"")); } function test_uninstall_executor_onuninstall_success() external unitTest { @@ -739,8 +742,10 @@ contract KernelTest is Test { } function test_install_hook() external unitTest { + assertTrue(kernel.supportsModule(4)); MockHook mockHook = new MockHook(); kernel.installModule(4, address(mockHook), abi.encode(hex"", "")); + assertTrue(kernel.isModuleInstalled(4, address(mockHook), hex"")); } function test_uninstall_hook() external unitTest { @@ -750,12 +755,14 @@ contract KernelTest is Test { } function test_install_validator() external unitTest { + assertTrue(kernel.supportsModule(1)); ValidationId vId = ValidationId.wrap(bytes20(address(newValidator))); kernel.installModule(1, address(newValidator), abi.encode(hex"deadbeef", "InternalData")); ValidationInfo memory vInfo = kernel.validationInfo(vId); assertTrue(vInfo.vType == VALIDATION_TYPE_VALIDATOR); bytes4 ret = kernel.isValidSignature(keccak256("Hello world"), abi.encodePacked(newValidator, _validatorSignHash(keccak256("Hello world"), true))); assertEq(ret, ERC1271_MAGICVALUE); + assertTrue(kernel.isModuleInstalled(1, address(newValidator), hex"")); } function test_uninstall_validator() external unitTest { @@ -769,6 +776,8 @@ contract KernelTest is Test { } function test_install_permission() external unitTest { + assertTrue(kernel.supportsModule(5)); + assertTrue(kernel.supportsModule(6)); ValidationId vId = ValidationId.wrap(permissionId); ValidationInfo memory vInfo = kernel.validationInfo(vId); assertTrue(vInfo.vType == VALIDATION_TYPE_ROOT); @@ -776,21 +785,25 @@ contract KernelTest is Test { kernel.installModule(6, address(signer), abi.encode(hex"deadbeef", abi.encodePacked(permissionId))); bytes4 ret = kernel.isValidSignature(keccak256("Hello world"), abi.encodePacked(permissionId, _permissionSignHash(keccak256("Hello world"), true))); assertEq(ret, ERC1271_MAGICVALUE); + assertTrue(kernel.isModuleInstalled(5, address(policy), abi.encodePacked(permissionId))); + assertTrue(kernel.isModuleInstalled(6, address(signer), abi.encodePacked(permissionId))); } function test_install_policy() external unitTest { + assertTrue(kernel.supportsModule(5)); MockPolicy mock = new MockPolicy(); - ValidationId vId = ValidationId.wrap(bytes20(keccak256(abi.encodePacked("deadbeef")))); + ValidationId vId = ValidationId.wrap(permissionId); ValidationInfo memory vInfo = kernel.validationInfo(vId); assertTrue(vInfo.vType == VALIDATION_TYPE_ROOT); kernel.installModule(5, address(mock), abi.encode(hex"deadbeef", abi.encodePacked(vId))); vInfo = kernel.validationInfo(vId); assertTrue(vInfo.vType == VALIDATION_TYPE_PERMISSION); + assertTrue(kernel.isModuleInstalled(5, address(mock), abi.encodePacked(permissionId))); } function test_uninstall_policy() external unitTest { MockPolicy mock = new MockPolicy(); - ValidationId vId = ValidationId.wrap(bytes20(keccak256(abi.encodePacked("deadbeef")))); + ValidationId vId = ValidationId.wrap(permissionId); ValidationInfo memory vInfo = kernel.validationInfo(vId); assertTrue(vInfo.vType == VALIDATION_TYPE_ROOT); kernel.installModule(5, address(mock), abi.encode(hex"deadbeef", abi.encodePacked(vId))); @@ -802,13 +815,15 @@ contract KernelTest is Test { } function test_install_signer() external unitTest { + assertTrue(kernel.supportsModule(6)); MockSigner mock = new MockSigner(); - ValidationId vId = ValidationId.wrap(bytes20(keccak256(abi.encodePacked("deadbeef")))); + ValidationId vId = ValidationId.wrap(permissionId); ValidationInfo memory vInfo = kernel.validationInfo(vId); assertTrue(vInfo.vType == VALIDATION_TYPE_ROOT); kernel.installModule(6, address(mock), abi.encode(hex"deadbeef", abi.encodePacked(vId))); vInfo = kernel.validationInfo(vId); assertTrue(vInfo.vType == VALIDATION_TYPE_PERMISSION); + assertTrue(kernel.isModuleInstalled(6, address(mock), abi.encodePacked(permissionId))); } function test_uninstall_signer() external unitTest { @@ -827,6 +842,7 @@ contract KernelTest is Test { } function test_install_selector_call() external unitTest { + assertTrue(kernel.supportsModule(3)); kernel.installModule( 3, address(mockFallback), @@ -842,6 +858,7 @@ contract KernelTest is Test { assertEq(address(c.target), address(mockFallback)); assertEq(address(c.hook), address(1)); assertTrue(c.callType == CallType.wrap(bytes1(0x00))); + assertTrue(kernel.isModuleInstalled(3, address(mockFallback), abi.encodePacked(MockFallback.fallbackFunction.selector))); } function test_install_selector_call_withhook() external unitTest { @@ -942,6 +959,7 @@ contract KernelTest is Test { function test_execute() external unitTest { vm.expectEmit(address(callee)); emit MockCallee.Lorem(); + assertEq(kernel.supportsExecutionMode(bytes32(0)), true); kernel.execute( bytes32(0), abi.encodePacked(address(callee), uint256(0), abi.encodeWithSelector(MockCallee.foo.selector)) ); @@ -957,24 +975,30 @@ contract KernelTest is Test { } function test_execute_fail_invalid_callType() external unitTest { + bytes32 mode = LibERC7579.encodeMode(bytes1(0x02), bytes1(0x01), bytes4(0), bytes22(0)); + assertEq(kernel.supportsExecutionMode(mode), false); vm.expectRevert(InvalidCallType.selector, address(kernel)); kernel.execute( - LibERC7579.encodeMode(bytes1(0x02), bytes1(0x01), bytes4(0), bytes22(0)), + mode, abi.encodePacked(address(callee), uint256(0), abi.encodeWithSelector(MockCallee.foo.selector)) ); } function test_execute_fail_invalid_execType() external unitTest { + bytes32 mode = LibERC7579.encodeMode(bytes1(0x00), bytes1(0x02), bytes4(0), bytes22(0)); + assertEq(kernel.supportsExecutionMode(mode), false); vm.expectRevert(InvalidExecType.selector, address(kernel)); kernel.execute( - LibERC7579.encodeMode(bytes1(0x00), bytes1(0x02), bytes4(0), bytes22(0)), + mode, abi.encodePacked(address(callee), uint256(0), abi.encodeWithSelector(MockCallee.foo.selector)) ); } function test_execute_fail_try() external unitTest { + bytes32 mode = LibERC7579.encodeMode(bytes1(0x00), bytes1(0x01), bytes4(0), bytes22(0)); + assertEq(kernel.supportsExecutionMode(mode), true); kernel.execute( - LibERC7579.encodeMode(bytes1(0x00), bytes1(0x01), bytes4(0), bytes22(0)), + mode, abi.encodePacked(address(callee), uint256(0), abi.encodeWithSelector(MockCallee.forceRevert.selector)) ); } @@ -984,9 +1008,11 @@ contract KernelTest is Test { calls[0] = Call({to: address(callee), value: 0, data: abi.encodeWithSelector(MockCallee.foo.selector)}); calls[1] = Call({to: address(callee), value: 0, data: abi.encodeWithSelector(MockCallee.lorem.selector)}); assertEq(callee.data(), ""); + bytes32 mode = LibERC7579.encodeMode(bytes1(0x01), bytes1(0x00), bytes4(0), bytes22(0)); + assertEq(kernel.supportsExecutionMode(mode), true); vm.expectEmit(address(callee)); emit MockCallee.Lorem(); - kernel.execute(LibERC7579.encodeMode(bytes1(0x01), bytes1(0x00), bytes4(0), bytes22(0)), abi.encode(calls)); + kernel.execute(mode, abi.encode(calls)); assertEq(callee.bar(), 1); assertEq(callee.data(), "lorem ipsum"); } @@ -996,6 +1022,8 @@ contract KernelTest is Test { calls[0] = Call({to: address(callee), value: 0, data: abi.encodeWithSelector(MockCallee.foo.selector)}); calls[1] = Call({to: address(callee), value: 0, data: abi.encodeWithSelector(MockCallee.forceRevert.selector)}); assertEq(callee.data(), ""); + bytes32 mode = LibERC7579.encodeMode(bytes1(0x01), bytes1(0x00), bytes4(0), bytes22(0)); + assertEq(kernel.supportsExecutionMode(mode), true); vm.expectRevert(MockCallee.Haha.selector); kernel.execute(LibERC7579.encodeMode(bytes1(0x01), bytes1(0x00), bytes4(0), bytes22(0)), abi.encode(calls)); } @@ -1005,11 +1033,15 @@ contract KernelTest is Test { calls[0] = Call({to: address(callee), value: 0, data: abi.encodeWithSelector(MockCallee.foo.selector)}); calls[1] = Call({to: address(callee), value: 0, data: abi.encodeWithSelector(MockCallee.forceRevert.selector)}); assertEq(callee.data(), ""); + bytes32 mode = LibERC7579.encodeMode(bytes1(0x01), bytes1(0x01), bytes4(0), bytes22(0)); + assertEq(kernel.supportsExecutionMode(mode), true); kernel.execute(LibERC7579.encodeMode(bytes1(0x01), bytes1(0x01), bytes4(0), bytes22(0)), abi.encode(calls)); assertEq(callee.bar(), 1); } function test_execute_delegatecall() external unitTest { + bytes32 mode = LibERC7579.encodeMode(bytes1(0xff), bytes1(0x00), bytes4(0), bytes22(0)); + assertEq(kernel.supportsExecutionMode(mode), true); vm.expectEmit(address(kernel)); emit MockCallee.Lorem(); kernel.execute( @@ -1027,6 +1059,8 @@ contract KernelTest is Test { } function test_execute_delegatecall_fail_try() external unitTest { + bytes32 mode = LibERC7579.encodeMode(bytes1(0xff), bytes1(0x01), bytes4(0), bytes22(0)); + assertEq(kernel.supportsExecutionMode(mode), true); kernel.execute( LibERC7579.encodeMode(bytes1(0xff), bytes1(0x01), bytes4(0), bytes22(0)), abi.encodePacked(address(callee), abi.encodeWithSelector(MockCallee.forceRevert.selector)) From 8ceebf0fcbefd33454a153d91d8182f00c20005f Mon Sep 17 00:00:00 2001 From: leekt Date: Wed, 28 May 2025 04:37:52 +0900 Subject: [PATCH 023/121] fmt --- src/Kernel.sol | 45 +++++++++++++++++----------------- src/KernelFactory.sol | 2 +- src/core/ValidationManager.sol | 18 ++++++++------ test/Kernel.t.sol | 24 ++++++++++-------- 4 files changed, 48 insertions(+), 41 deletions(-) diff --git a/src/Kernel.sol b/src/Kernel.sol index 0c64d321..aadd606e 100644 --- a/src/Kernel.sol +++ b/src/Kernel.sol @@ -218,56 +218,57 @@ contract Kernel is ModuleManager, ExecutionManager, UUPSUpgradeable { emit Received(msg.sender, msg.value); } - function supportsExecutionMode(bytes32 mode) external view returns(bool) { + function supportsExecutionMode(bytes32 mode) external view returns (bool) { bytes1 callType = LibERC7579.getCallType(mode); bytes1 execType = LibERC7579.getExecType(mode); - if (execType == LibERC7579.EXECTYPE_DEFAULT) { - } else if (execType == LibERC7579.EXECTYPE_TRY) { - } else { + if (execType == LibERC7579.EXECTYPE_DEFAULT) {} else if (execType == LibERC7579.EXECTYPE_TRY) {} else { return false; } - if (callType == LibERC7579.CALLTYPE_SINGLE) { - } else if (callType == LibERC7579.CALLTYPE_BATCH) { - } else if (callType == LibERC7579.CALLTYPE_DELEGATECALL) { - } else { + if (callType == LibERC7579.CALLTYPE_SINGLE) {} else if (callType == LibERC7579.CALLTYPE_BATCH) {} else if ( + callType == LibERC7579.CALLTYPE_DELEGATECALL + ) {} else { return false; } return true; } - function supportsModule(uint256 moduleTypeId) external view returns(bool) { + function supportsModule(uint256 moduleTypeId) external view returns (bool) { return moduleTypeId < 7; } - function isModuleInstalled(uint256 moduleTypeId, address module, bytes calldata additionalContext) external view returns(bool) { - if(moduleTypeId == 1) { + function isModuleInstalled(uint256 moduleTypeId, address module, bytes calldata additionalContext) + external + view + returns (bool) + { + if (moduleTypeId == 1) { ValidationId vId = ValidationId.wrap(bytes20(module)); return !(_validationStorage().vInfo[vId].vType == VALIDATION_TYPE_ROOT); - } else if(moduleTypeId == 2) { + } else if (moduleTypeId == 2) { return address(_executorConfig(IExecutor(module)).hook) != address(0); - } else if(moduleTypeId == 3) { + } else if (moduleTypeId == 3) { bytes4 selector = bytes4(additionalContext); return _selectorConfig(selector).target == module; - } else if(moduleTypeId == 4) { + } else if (moduleTypeId == 4) { return _hookStorage().enabled[module]; - } else if(moduleTypeId == 5) { + } else if (moduleTypeId == 5) { ValidationId vId = ValidationId.wrap(bytes20(additionalContext)); - ValidationInfo storage $ =_validationStorage().vInfo[vId]; - for(uint256 i = 0; i < $.policies.length; i++) { - if($.policies[i] == module) { + ValidationInfo storage $ = _validationStorage().vInfo[vId]; + for (uint256 i = 0; i < $.policies.length; i++) { + if ($.policies[i] == module) { return true; } } - return false; - } else if(moduleTypeId == 6) { + return false; + } else if (moduleTypeId == 6) { ValidationId vId = ValidationId.wrap(bytes20(additionalContext)); - ValidationInfo storage $ =_validationStorage().vInfo[vId]; + ValidationInfo storage $ = _validationStorage().vInfo[vId]; return $.signer == module; } else { revert NotImplemented(); } } - + function accountId() external view returns (string memory accountImplementationId) { return "kernel.v0.4"; } diff --git a/src/KernelFactory.sol b/src/KernelFactory.sol index 115b77b8..6686c4c4 100644 --- a/src/KernelFactory.sol +++ b/src/KernelFactory.sol @@ -33,7 +33,7 @@ contract KernelFactory { if (!deployed) { k.installModule(true, 0, initialPackages, hex""); } - (bool success, ) = address(k).call(extraCall); + (bool success,) = address(k).call(extraCall); require(success, "call failed"); return k; } diff --git a/src/core/ValidationManager.sol b/src/core/ValidationManager.sol index 64a3900f..e53bed1a 100644 --- a/src/core/ValidationManager.sol +++ b/src/core/ValidationManager.sol @@ -140,22 +140,24 @@ abstract contract ValidationManager { return _verify7702Signature(_hash, _signature) ? 0 : 1; } ValidationInfo storage vInfo = _validationStorage().vInfo[vId]; - if(vInfo.vType == VALIDATION_TYPE_VALIDATOR) { + if (vInfo.vType == VALIDATION_TYPE_VALIDATOR) { IValidator validator = IValidator(address(ValidationId.unwrap(vId))); // TODO: add permission support; validationData = validator.isValidSignatureWithSender(requester, /*NOTE: fix this */ _hash, _signature) - == ERC1271_MAGICVALUE ? 0 : 1; - } else if(vInfo.vType == VALIDATION_TYPE_PERMISSION) { + == ERC1271_MAGICVALUE ? 0 : 1; + } else if (vInfo.vType == VALIDATION_TYPE_PERMISSION) { return _verifySignaturePermission(vId, vInfo, requester, _hash, _signature); } else { return 1; } } - function _verifySignaturePermission(ValidationId vId, ValidationInfo storage vInfo, address requester, bytes32 _hash, bytes calldata _signature) - internal - view - returns (uint256 validationData) - { + function _verifySignaturePermission( + ValidationId vId, + ValidationInfo storage vInfo, + address requester, + bytes32 _hash, + bytes calldata _signature + ) internal view returns (uint256 validationData) { unchecked { uint256 length = vInfo.policies.length + 1; diff --git a/test/Kernel.t.sol b/test/Kernel.t.sol index af2b0c47..a0bca74a 100644 --- a/test/Kernel.t.sol +++ b/test/Kernel.t.sol @@ -653,7 +653,7 @@ contract KernelTest is Test { Kernel k = factory.deploy(pkgs, 1); assertEq(address(k), address(factory.deploy(pkgs, 1))); } - + function test_deploy_with_call() external unitTest { Install[] memory initPkgs = new Install[](1); initPkgs[0] = Install({moduleType: 1, module: address(mockValidator), moduleData: hex"", internalData: hex""}); @@ -760,7 +760,9 @@ contract KernelTest is Test { kernel.installModule(1, address(newValidator), abi.encode(hex"deadbeef", "InternalData")); ValidationInfo memory vInfo = kernel.validationInfo(vId); assertTrue(vInfo.vType == VALIDATION_TYPE_VALIDATOR); - bytes4 ret = kernel.isValidSignature(keccak256("Hello world"), abi.encodePacked(newValidator, _validatorSignHash(keccak256("Hello world"), true))); + bytes4 ret = kernel.isValidSignature( + keccak256("Hello world"), abi.encodePacked(newValidator, _validatorSignHash(keccak256("Hello world"), true)) + ); assertEq(ret, ERC1271_MAGICVALUE); assertTrue(kernel.isModuleInstalled(1, address(newValidator), hex"")); } @@ -783,7 +785,10 @@ contract KernelTest is Test { assertTrue(vInfo.vType == VALIDATION_TYPE_ROOT); kernel.installModule(5, address(policy), abi.encode(hex"deadbeef", abi.encodePacked(permissionId))); kernel.installModule(6, address(signer), abi.encode(hex"deadbeef", abi.encodePacked(permissionId))); - bytes4 ret = kernel.isValidSignature(keccak256("Hello world"), abi.encodePacked(permissionId, _permissionSignHash(keccak256("Hello world"), true))); + bytes4 ret = kernel.isValidSignature( + keccak256("Hello world"), + abi.encodePacked(permissionId, _permissionSignHash(keccak256("Hello world"), true)) + ); assertEq(ret, ERC1271_MAGICVALUE); assertTrue(kernel.isModuleInstalled(5, address(policy), abi.encodePacked(permissionId))); assertTrue(kernel.isModuleInstalled(6, address(signer), abi.encodePacked(permissionId))); @@ -858,7 +863,9 @@ contract KernelTest is Test { assertEq(address(c.target), address(mockFallback)); assertEq(address(c.hook), address(1)); assertTrue(c.callType == CallType.wrap(bytes1(0x00))); - assertTrue(kernel.isModuleInstalled(3, address(mockFallback), abi.encodePacked(MockFallback.fallbackFunction.selector))); + assertTrue( + kernel.isModuleInstalled(3, address(mockFallback), abi.encodePacked(MockFallback.fallbackFunction.selector)) + ); } function test_install_selector_call_withhook() external unitTest { @@ -979,8 +986,7 @@ contract KernelTest is Test { assertEq(kernel.supportsExecutionMode(mode), false); vm.expectRevert(InvalidCallType.selector, address(kernel)); kernel.execute( - mode, - abi.encodePacked(address(callee), uint256(0), abi.encodeWithSelector(MockCallee.foo.selector)) + mode, abi.encodePacked(address(callee), uint256(0), abi.encodeWithSelector(MockCallee.foo.selector)) ); } @@ -989,8 +995,7 @@ contract KernelTest is Test { assertEq(kernel.supportsExecutionMode(mode), false); vm.expectRevert(InvalidExecType.selector, address(kernel)); kernel.execute( - mode, - abi.encodePacked(address(callee), uint256(0), abi.encodeWithSelector(MockCallee.foo.selector)) + mode, abi.encodePacked(address(callee), uint256(0), abi.encodeWithSelector(MockCallee.foo.selector)) ); } @@ -998,8 +1003,7 @@ contract KernelTest is Test { bytes32 mode = LibERC7579.encodeMode(bytes1(0x00), bytes1(0x01), bytes4(0), bytes22(0)); assertEq(kernel.supportsExecutionMode(mode), true); kernel.execute( - mode, - abi.encodePacked(address(callee), uint256(0), abi.encodeWithSelector(MockCallee.forceRevert.selector)) + mode, abi.encodePacked(address(callee), uint256(0), abi.encodeWithSelector(MockCallee.forceRevert.selector)) ); } From 4a82d118eddc76513a9f09e64151a59e2ed80c65 Mon Sep 17 00:00:00 2001 From: leekt Date: Wed, 28 May 2025 15:37:04 +0900 Subject: [PATCH 024/121] fix: typehash for individual hash --- src/KernelHelper.sol | 7 ++++++- src/core/ModuleManager.sol | 3 +++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/KernelHelper.sol b/src/KernelHelper.sol index 78c1985b..cc1e63aa 100644 --- a/src/KernelHelper.sol +++ b/src/KernelHelper.sol @@ -64,7 +64,12 @@ contract KernelHelper { for (uint256 i = 0; i < packages.length; i++) { Install calldata pkg = packages[i]; packageHashes[i] = keccak256( - abi.encode(pkg.moduleType, pkg.module, calldataKeccak(pkg.moduleData), calldataKeccak(pkg.internalData)) + abi.encode( + keccak256( + "Install(uint256 moduleType,address module,bytes moduleData,bytes internalData)" + ), + pkg.moduleType, pkg.module, calldataKeccak(pkg.moduleData), calldataKeccak(pkg.internalData) + ) ); } return keccak256(abi.encodePacked(packageHashes)); diff --git a/src/core/ModuleManager.sol b/src/core/ModuleManager.sol index e6248eac..6a491601 100644 --- a/src/core/ModuleManager.sol +++ b/src/core/ModuleManager.sol @@ -49,6 +49,9 @@ abstract contract ModuleManager is ValidationManager, ExecutorManager, HookManag Install calldata pkg = packages[i]; packageHashes[i] = keccak256( abi.encode( + keccak256( + "Install(uint256 moduleType,address module,bytes moduleData,bytes internalData)" + ), pkg.moduleType, pkg.module, calldataKeccak(pkg.moduleData), calldataKeccak(pkg.internalData) ) ); From 47c5c91eaa026144f629e504f3a7fe24672c9123 Mon Sep 17 00:00:00 2001 From: leekt Date: Wed, 28 May 2025 19:59:19 +0900 Subject: [PATCH 025/121] fix kernel helper same hash --- src/KernelHelper.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/KernelHelper.sol b/src/KernelHelper.sol index cc1e63aa..e156f84d 100644 --- a/src/KernelHelper.sol +++ b/src/KernelHelper.sol @@ -106,8 +106,8 @@ contract KernelHelper { mstore(add(m, 0x20), separator) // Name hash. mstore(add(m, 0x40), versionHash) mstore(add(m, 0x60), chainid()) - mstore(add(m, 0x80), address()) - separator := keccak256(m, 0xa0) + mstore(add(m, 0x80), addr) + digest := keccak256(m, 0xa0) // Compute the digest. mstore(0x00, 0x1901000000000000) // Store "\x19\x01". mstore(0x1a, digest) // Store the domain separator. From 7200ea5e43434506da1a1ce6591f409271c80ef0 Mon Sep 17 00:00:00 2001 From: leekt Date: Wed, 28 May 2025 19:59:26 +0900 Subject: [PATCH 026/121] todo: working on 7702 --- src/Kernel.sol | 7 ++--- src/core/ModuleManager.sol | 9 ++++--- src/lib/Lib4337.sol | 8 +++--- test/Kernel.t.sol | 28 +++++++++++++++++--- test/Kernel7702.t.sol | 32 +++++++++++++++++++++++ test/mock/MockKernel.sol | 53 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 122 insertions(+), 15 deletions(-) create mode 100644 test/Kernel7702.t.sol create mode 100644 test/mock/MockKernel.sol diff --git a/src/Kernel.sol b/src/Kernel.sol index aadd606e..c38c6401 100644 --- a/src/Kernel.sol +++ b/src/Kernel.sol @@ -221,11 +221,12 @@ contract Kernel is ModuleManager, ExecutionManager, UUPSUpgradeable { function supportsExecutionMode(bytes32 mode) external view returns (bool) { bytes1 callType = LibERC7579.getCallType(mode); bytes1 execType = LibERC7579.getExecType(mode); - if (execType == LibERC7579.EXECTYPE_DEFAULT) {} else if (execType == LibERC7579.EXECTYPE_TRY) {} else { + if (execType == LibERC7579.EXECTYPE_DEFAULT || execType == LibERC7579.EXECTYPE_TRY) {} else { return false; } - if (callType == LibERC7579.CALLTYPE_SINGLE) {} else if (callType == LibERC7579.CALLTYPE_BATCH) {} else if ( - callType == LibERC7579.CALLTYPE_DELEGATECALL + if ( + callType == LibERC7579.CALLTYPE_SINGLE || callType == LibERC7579.CALLTYPE_BATCH + || callType == LibERC7579.CALLTYPE_DELEGATECALL ) {} else { return false; } diff --git a/src/core/ModuleManager.sol b/src/core/ModuleManager.sol index 6a491601..49c7f210 100644 --- a/src/core/ModuleManager.sol +++ b/src/core/ModuleManager.sol @@ -49,10 +49,11 @@ abstract contract ModuleManager is ValidationManager, ExecutorManager, HookManag Install calldata pkg = packages[i]; packageHashes[i] = keccak256( abi.encode( - keccak256( - "Install(uint256 moduleType,address module,bytes moduleData,bytes internalData)" - ), - pkg.moduleType, pkg.module, calldataKeccak(pkg.moduleData), calldataKeccak(pkg.internalData) + keccak256("Install(uint256 moduleType,address module,bytes moduleData,bytes internalData)"), + pkg.moduleType, + pkg.module, + calldataKeccak(pkg.moduleData), + calldataKeccak(pkg.internalData) ) ); } diff --git a/src/lib/Lib4337.sol b/src/lib/Lib4337.sol index fa280d36..22a7185d 100644 --- a/src/lib/Lib4337.sol +++ b/src/lib/Lib4337.sol @@ -11,7 +11,7 @@ library Lib4337 { bytes32 internal constant _DOMAIN_TYPEHASH_SANS_CHAIN_ID = 0x91ab3d17e3a50a9d89e63fd30b92be7f5336b03b287bb946787a83a9d62a2766; - function chainAgnosticUserOpHash(address ep, PackedUserOperation calldata userOp) external view returns (bytes32) { + function chainAgnosticUserOpHash(address ep, PackedUserOperation calldata userOp) internal view returns (bytes32) { bytes32 overrideInitCodeHash = Eip7702Support._getEip7702InitCodeHashOverride(userOp); return _hashTypedDataSansChainId(ep, UserOperationLib.hash(userOp, overrideInitCodeHash)); } @@ -30,7 +30,7 @@ library Lib4337 { } } - function checkValidation(uint256 validationData) external view returns (bool) { + function checkValidation(uint256 validationData) internal view returns (bool) { (uint48 vAfter, uint48 vUntil, address res) = Lib4337.parseValidationData(validationData); if (vAfter > block.timestamp || vUntil < block.timestamp) { return false; @@ -59,11 +59,11 @@ library Lib4337 { } } - function intersectValidationData(uint256 a, bytes4 res) external pure returns (uint256) { + function intersectValidationData(uint256 a, bytes4 res) internal pure returns (uint256) { return _intersectValidationData(a, signatureResultToValidationData(res)); } - function intersectValidationData(uint256 a, uint256 b) external pure returns (uint256 validationData) { + function intersectValidationData(uint256 a, uint256 b) internal pure returns (uint256 validationData) { return _intersectValidationData(a, b); } diff --git a/test/Kernel.t.sol b/test/Kernel.t.sol index a0bca74a..ac5b36ea 100644 --- a/test/Kernel.t.sol +++ b/test/Kernel.t.sol @@ -18,6 +18,7 @@ import {MockPolicy} from "./mock/MockPolicy.sol"; import {MockSigner} from "./mock/MockSigner.sol"; import {MockERC721} from "./mock/MockERC721.sol"; import {MockERC1155} from "./mock/MockERC1155.sol"; +import {MockKernel} from "./mock/MockKernel.sol"; import {IHook} from "src/interfaces/IERC7579Modules.sol"; import {CallType} from "src/types/Types.sol"; import "src/types/Constants.sol"; @@ -74,6 +75,8 @@ contract KernelTest is Test { uint256 permissionRevertIndex; KernelHelper helper; + bool is7702; + modifier unitTest() { vm.startPrank(address(ep)); _; @@ -106,7 +109,7 @@ contract KernelTest is Test { _initialize(); } - function _initialize() internal { + function _initialize() internal virtual { Install[] memory pkgs = new Install[](1); pkgs[0] = Install({moduleType: 1, module: address(mockValidator), moduleData: hex"", internalData: hex""}); kernel = factory.deploy(pkgs, 0); @@ -119,13 +122,14 @@ contract KernelTest is Test { function _rootSignUserOp(PackedUserOperation memory op, bool success, bool replay) internal + virtual returns (bytes memory sig) { mockValidator.sudoSetSuccess(success); return hex""; } - function _rootSignHash(bytes32 hash, bool success) internal returns (bytes memory sig) { + function _rootSignHash(bytes32 hash, bool success) internal virtual returns (bytes memory sig) { if (success) { mockValidator.sudoSetValidSig(hex""); } @@ -134,13 +138,14 @@ contract KernelTest is Test { function _validatorSignUserOp(PackedUserOperation memory op, bool success, bool replay) internal + virtual returns (bytes memory sig) { newValidator.sudoSetSuccess(success); return hex""; } - function _validatorSignHash(bytes32 hash, bool success) internal returns (bytes memory sig) { + function _validatorSignHash(bytes32 hash, bool success) internal virtual returns (bytes memory sig) { if (success) { newValidator.sudoSetValidSig(hex""); } @@ -149,6 +154,7 @@ contract KernelTest is Test { function _permissionSignUserOp(PackedUserOperation memory op, bool success, bool replay) internal + virtual returns (bytes memory sig) { bytes[] memory signatures = new bytes[](2); @@ -164,7 +170,7 @@ contract KernelTest is Test { return abi.encode(signatures); } - function _permissionSignHash(bytes32 hash, bool success) internal returns (bytes memory sig) { + function _permissionSignHash(bytes32 hash, bool success) internal virtual returns (bytes memory sig) { bytes[] memory signatures = new bytes[](2); signatures[0] = hex"dead"; signatures[1] = hex"beef"; @@ -182,6 +188,10 @@ contract KernelTest is Test { function(bytes32, bool) internal returns(bytes memory) signEnable ) internal returns (bytes memory sig) { bytes32 digest = helper.installDigest(address(kernel), replayable, nonce, packages); + MockKernel mockKernel = new MockKernel(ep); + + vm.store(address(kernel), ERC1967_IMPLEMENTATION_SLOT, bytes32(uint256(uint160(address(mockKernel))))); + assertEq(MockKernel(payable(address(kernel))).installDigest(replayable, nonce, packages), digest); return signEnable(digest, enableSuccess); } @@ -642,12 +652,14 @@ contract KernelTest is Test { } function test_deploy() external unitTest { + vm.skip(is7702); Install[] memory pkgs = new Install[](1); pkgs[0] = Install({moduleType: 1, module: address(mockValidator), moduleData: hex"", internalData: hex""}); Kernel k = factory.deploy(pkgs, 1); } function test_deploy_existing() external { + vm.skip(is7702); Install[] memory pkgs = new Install[](1); pkgs[0] = Install({moduleType: 1, module: address(mockValidator), moduleData: hex"", internalData: hex""}); Kernel k = factory.deploy(pkgs, 1); @@ -655,6 +667,7 @@ contract KernelTest is Test { } function test_deploy_with_call() external unitTest { + vm.skip(is7702); Install[] memory initPkgs = new Install[](1); initPkgs[0] = Install({moduleType: 1, module: address(mockValidator), moduleData: hex"", internalData: hex""}); Install[] memory pkgs = new Install[](1); @@ -1103,6 +1116,13 @@ contract KernelTest is Test { InstallAndExecute memory ie = InstallAndExecute({replayable: replayable, nonce: nonce, packages: packages, signature: hex""}); bytes32 hash = helper.installAndExecuteDigest(address(kernel), MODE_EXECUTE_WITH_OP_DATA, calls, ie); + + MockKernel mockKernel = new MockKernel(ep); + + vm.store(address(kernel), ERC1967_IMPLEMENTATION_SLOT, bytes32(uint256(uint160(address(mockKernel))))); + assertEq( + MockKernel(payable(address(kernel))).installAndExecuteDigest(MODE_EXECUTE_WITH_OP_DATA, calls, ie), hash + ); sig = abi.encode(false, uint256(0), packages, _rootSignHash(hash, true)); } diff --git a/test/Kernel7702.t.sol b/test/Kernel7702.t.sol new file mode 100644 index 00000000..6212eeaa --- /dev/null +++ b/test/Kernel7702.t.sol @@ -0,0 +1,32 @@ +pragma solidity ^0.8.0; + +import "./Kernel.t.sol"; +contract Kernel7702Test is KernelTest { + address owner; + uint256 ownerKey; + function _initialize() internal override { + is7702 = true; + kernel = Kernel(payable(owner)); + vm.etch(owner, abi.encodePacked(bytes3(0xef0100), address(factory.template()))); + vm.deal(owner, 1e18); + + vm.startPrank(address(ep)); + kernel.installModule(2, executor, abi.encode(hex"", hex"")); + vm.stopPrank(); + } + + function _rootSignUserOp(PackedUserOperation memory op, bool success, bool replay) + internal + override + returns (bytes memory sig) + { + bytes32 hash = ep.getUserOpHash(op); + return _rootSignHash(hash, success); + } + + function _rootSignHash(bytes32 hash, bool success) internal override returns (bytes memory sig) { + (uint8 v, bytes32 r, bytes32 s) = vm.sign(ownerKey, hash); + return abi.encodePacked(r,s,v); + } + +} diff --git a/test/mock/MockKernel.sol b/test/mock/MockKernel.sol new file mode 100644 index 00000000..440888a9 --- /dev/null +++ b/test/mock/MockKernel.sol @@ -0,0 +1,53 @@ +pragma solidity ^0.8.0; + +import "src/Kernel.sol"; +import "forge-std/console.sol"; + +// NOTE: this is not for real usecase, just a contract to deploy for test checks +contract MockKernel is Kernel { + constructor(IEntryPoint ep) Kernel(ep) {} + + function installAndExecuteDigest(bytes32 mode, Call[] calldata calls, InstallAndExecute calldata opData) + external + view + returns (bytes32) + { + function(bytes32) internal view returns(bytes32) hashTypedData = + opData.replayable ? _hashTypedDataSansChainId : _hashTypedData; + bytes32 digest = hashTypedData( + keccak256( + abi.encode( + keccak256( + "ExecuteWithInstall(bytes32 mode, bytes execData,uint256 nonce,Install[] packages)Install(uint256 moduleType,address module,bytes moduleData,bytes internalData)" + ), + mode, + keccak256(abi.encode(calls)), + opData.nonce, + _installHash(opData.packages) + ) + ) + ); + return digest; + } + + function installDigest(bool replayable, uint256 nonce, Install[] calldata packages) + external + view + returns (bytes32) + { + function(bytes32) internal view returns(bytes32) hashTypedData = + replayable ? _hashTypedDataSansChainId : _hashTypedData; + bytes32 digest = hashTypedData( + keccak256( + abi.encode( + keccak256( + "InstallPackages(uint256 nonce,Install[] packages)Install(uint256 moduleType,address module,bytes moduleData,bytes internalData)" + ), + nonce, + _installHash(packages) + ) + ) + ); + return digest; + } +} From 965ca657b014d21013acc27044854921d26ff592 Mon Sep 17 00:00:00 2001 From: leekt Date: Wed, 28 May 2025 20:18:19 +0900 Subject: [PATCH 027/121] 7702 tested --- src/KernelHelper.sol | 9 +++++---- src/core/ValidationManager.sol | 10 +++++----- src/lib/Lib4337.sol | 2 +- test/Kernel.t.sol | 16 ++++++++++------ test/Kernel7702.t.sol | 14 ++++++++++---- 5 files changed, 31 insertions(+), 20 deletions(-) diff --git a/src/KernelHelper.sol b/src/KernelHelper.sol index e156f84d..7ae59d64 100644 --- a/src/KernelHelper.sol +++ b/src/KernelHelper.sol @@ -65,10 +65,11 @@ contract KernelHelper { Install calldata pkg = packages[i]; packageHashes[i] = keccak256( abi.encode( - keccak256( - "Install(uint256 moduleType,address module,bytes moduleData,bytes internalData)" - ), - pkg.moduleType, pkg.module, calldataKeccak(pkg.moduleData), calldataKeccak(pkg.internalData) + keccak256("Install(uint256 moduleType,address module,bytes moduleData,bytes internalData)"), + pkg.moduleType, + pkg.module, + calldataKeccak(pkg.moduleData), + calldataKeccak(pkg.internalData) ) ); } diff --git a/src/core/ValidationManager.sol b/src/core/ValidationManager.sol index e53bed1a..00d2c889 100644 --- a/src/core/ValidationManager.sol +++ b/src/core/ValidationManager.sol @@ -122,12 +122,12 @@ abstract contract ValidationManager { require($.vInfo[vId].vType == vType, InvalidValidator()); } - if (vType == VALIDATION_TYPE_VALIDATOR) { - validateUserOp = _validateUserOpValidator; - } else if (vType == VALIDATION_TYPE_PERMISSION) { + if (vType == VALIDATION_TYPE_PERMISSION) { validateUserOp = _validateUserOpPermission; } else { - revert InvalidValidationType(); + // this includes 7702 + validateUserOp = _validateUserOpValidator; + //revert InvalidValidationType(); } } @@ -231,7 +231,7 @@ abstract contract ValidationManager { } function _verify7702Signature(bytes32 hash, bytes calldata sig) internal view returns (bool) { - return ECDSA.recover(hash, sig) == address(this); + return ECDSA.tryRecover(hash, sig) == address(this); } function _setRoot(Install calldata pkg) internal { diff --git a/src/lib/Lib4337.sol b/src/lib/Lib4337.sol index 22a7185d..ae2661bd 100644 --- a/src/lib/Lib4337.sol +++ b/src/lib/Lib4337.sol @@ -11,7 +11,7 @@ library Lib4337 { bytes32 internal constant _DOMAIN_TYPEHASH_SANS_CHAIN_ID = 0x91ab3d17e3a50a9d89e63fd30b92be7f5336b03b287bb946787a83a9d62a2766; - function chainAgnosticUserOpHash(address ep, PackedUserOperation calldata userOp) internal view returns (bytes32) { + function chainAgnosticUserOpHash(address ep, PackedUserOperation calldata userOp) external view returns (bytes32) { bytes32 overrideInitCodeHash = Eip7702Support._getEip7702InitCodeHashOverride(userOp); return _hashTypedDataSansChainId(ep, UserOperationLib.hash(userOp, overrideInitCodeHash)); } diff --git a/test/Kernel.t.sol b/test/Kernel.t.sol index ac5b36ea..5d589709 100644 --- a/test/Kernel.t.sol +++ b/test/Kernel.t.sol @@ -190,8 +190,10 @@ contract KernelTest is Test { bytes32 digest = helper.installDigest(address(kernel), replayable, nonce, packages); MockKernel mockKernel = new MockKernel(ep); - vm.store(address(kernel), ERC1967_IMPLEMENTATION_SLOT, bytes32(uint256(uint160(address(mockKernel))))); - assertEq(MockKernel(payable(address(kernel))).installDigest(replayable, nonce, packages), digest); + if (!is7702) { + vm.store(address(kernel), ERC1967_IMPLEMENTATION_SLOT, bytes32(uint256(uint160(address(mockKernel))))); + assertEq(MockKernel(payable(address(kernel))).installDigest(replayable, nonce, packages), digest); + } return signEnable(digest, enableSuccess); } @@ -1119,10 +1121,12 @@ contract KernelTest is Test { MockKernel mockKernel = new MockKernel(ep); - vm.store(address(kernel), ERC1967_IMPLEMENTATION_SLOT, bytes32(uint256(uint160(address(mockKernel))))); - assertEq( - MockKernel(payable(address(kernel))).installAndExecuteDigest(MODE_EXECUTE_WITH_OP_DATA, calls, ie), hash - ); + if (!is7702) { + vm.store(address(kernel), ERC1967_IMPLEMENTATION_SLOT, bytes32(uint256(uint160(address(mockKernel))))); + assertEq( + MockKernel(payable(address(kernel))).installAndExecuteDigest(MODE_EXECUTE_WITH_OP_DATA, calls, ie), hash + ); + } sig = abi.encode(false, uint256(0), packages, _rootSignHash(hash, true)); } diff --git a/test/Kernel7702.t.sol b/test/Kernel7702.t.sol index 6212eeaa..a96f727f 100644 --- a/test/Kernel7702.t.sol +++ b/test/Kernel7702.t.sol @@ -1,11 +1,15 @@ pragma solidity ^0.8.0; import "./Kernel.t.sol"; +import {Lib4337} from "src/lib/Lib4337.sol"; + contract Kernel7702Test is KernelTest { address owner; uint256 ownerKey; + function _initialize() internal override { is7702 = true; + (owner, ownerKey) = makeAddrAndKey("Owner"); kernel = Kernel(payable(owner)); vm.etch(owner, abi.encodePacked(bytes3(0xef0100), address(factory.template()))); vm.deal(owner, 1e18); @@ -14,19 +18,21 @@ contract Kernel7702Test is KernelTest { kernel.installModule(2, executor, abi.encode(hex"", hex"")); vm.stopPrank(); } - + function _rootSignUserOp(PackedUserOperation memory op, bool success, bool replay) internal override returns (bytes memory sig) { - bytes32 hash = ep.getUserOpHash(op); + bytes32 hash = replay ? Lib4337.chainAgnosticUserOpHash(address(ep), op) : ep.getUserOpHash(op); return _rootSignHash(hash, success); } function _rootSignHash(bytes32 hash, bool success) internal override returns (bytes memory sig) { + if (!success) { + hash = keccak256(abi.encodePacked(hash)); + } (uint8 v, bytes32 r, bytes32 s) = vm.sign(ownerKey, hash); - return abi.encodePacked(r,s,v); + return abi.encodePacked(r, s, v); } - } From a7b95fffea27f0d8b366f2f1381cdfc7ebf85ae4 Mon Sep 17 00:00:00 2001 From: leekt Date: Wed, 28 May 2025 21:33:36 +0900 Subject: [PATCH 028/121] erc1271 flow tested --- foundry.toml | 1 + src/Kernel.sol | 11 ---- src/KernelHelper.sol | 2 +- src/core/ModuleManager.sol | 23 ++++++++ test/Kernel.t.sol | 112 +++++++++++++++++++++++++++++++++++++ 5 files changed, 137 insertions(+), 12 deletions(-) diff --git a/foundry.toml b/foundry.toml index 2c9d3a5b..d3d1b49c 100644 --- a/foundry.toml +++ b/foundry.toml @@ -5,5 +5,6 @@ libs = ["lib"] via_ir = false optimizer = true run = 200 +evm_version = 'prague' # See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options diff --git a/src/Kernel.sol b/src/Kernel.sol index c38c6401..8f3fc72c 100644 --- a/src/Kernel.sol +++ b/src/Kernel.sol @@ -90,17 +90,6 @@ contract Kernel is ModuleManager, ExecutionManager, UUPSUpgradeable { Lib4337.intersectValidationData(validationData, validateUserOpFn(vId, opHash, userOp, signature)); } - function _erc1271IsValidSignatureNowCalldata(bytes32 hash, bytes calldata signature) - internal - view - override - returns (bool) - { - ValidationId vId = ValidationId.wrap(bytes20(signature[0:20])); - uint256 validationData = _verifySignature(vId, msg.sender, hash, signature[20:]); - return Lib4337.checkValidation(validationData); - } - /// execution function executeUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash) external payable { _onlyEntryPointOrSelf(); diff --git a/src/KernelHelper.sol b/src/KernelHelper.sol index 7ae59d64..62e7d8b8 100644 --- a/src/KernelHelper.sol +++ b/src/KernelHelper.sol @@ -76,7 +76,7 @@ contract KernelHelper { return keccak256(abi.encodePacked(packageHashes)); } - function _hashTypedDataSansChainId(address addr, bytes32 structHash) public view returns (bytes32 digest) { + function _hashTypedDataSansChainId(address addr, bytes32 structHash) internal view returns (bytes32 digest) { (, string memory name, string memory version,,,,) = IERC5267(addr).eip712Domain(); /// @solidity memory-safe-assembly assembly { diff --git a/src/core/ModuleManager.sol b/src/core/ModuleManager.sol index 49c7f210..e130bbbf 100644 --- a/src/core/ModuleManager.sol +++ b/src/core/ModuleManager.sol @@ -41,6 +41,29 @@ abstract contract ModuleManager is ValidationManager, ExecutorManager, HookManag function _erc1271Signer() internal view override returns (address) { return address(1); } + + function _erc1271IsValidSignature(bytes32 hash, bytes calldata signature) + internal + view + override + returns (bool) + { + return _erc1271IsValidSignatureViaNestedEIP712(hash, signature); + } + + function _erc1271IsValidSignatureNowCalldata(bytes32 hash, bytes calldata signature) + internal + view + override + returns (bool) + { + ValidationId vId = ValidationId.wrap(bytes20(signature[0:20])); + if(vId == ValidationId.wrap(bytes20(0))){ + vId = _validationStorage().root; + } + uint256 validationData = _verifySignature(vId, msg.sender, hash, signature[20:]); + return Lib4337.checkValidation(validationData); + } function _installHash(Install[] calldata packages) internal pure returns (bytes32) { bytes32[] memory packageHashes = new bytes32[](packages.length); diff --git a/test/Kernel.t.sol b/test/Kernel.t.sol index 5d589709..54fa03e9 100644 --- a/test/Kernel.t.sol +++ b/test/Kernel.t.sol @@ -9,6 +9,7 @@ import {KernelHelper} from "src/KernelHelper.sol"; import {SelectorManager} from "src/core/SelectorManager.sol"; import {KernelFactory} from "src/KernelFactory.sol"; import {LibERC7579} from "solady/accounts/LibERC7579.sol"; +import {LibString} from "solady/utils/LibString.sol"; import {Install} from "src/types/Structs.sol"; import {MockFallback} from "./mock/MockFallback.sol"; import {MockExecutor} from "./mock/MockExecutor.sol"; @@ -744,6 +745,24 @@ contract KernelTest is Test { assertEq(address(uint160(uint256(impl))), address(newTemplate)); } + function test_erc1271_root() external { + bytes32 messageHash = keccak256("Hello world"); + //function _erc1271Signature( + // bytes32 hash, + // bytes memory contentsType, + // bytes memory contentsName, + // function(bytes32, bool) returns(bytes memory) signFn, + // bool isExplicit, + // bool success + //) internal returns(bytes memory sig){ + + (bytes32 contentsHash, bytes memory sig) = _erc1271Signature(messageHash,"C(bytes32 stuff)", "", _rootSignHash, false, true); + bytes4 ret = kernel.isValidSignature( + _toContentsHash(contentsHash), abi.encodePacked(bytes20(0), sig ) + ); + assertEq(ret, ERC1271_MAGICVALUE); + } + function test_install_invalid() external unitTest { MockHook mockHook = new MockHook(); vm.expectRevert(NotImplemented.selector); @@ -1157,4 +1176,97 @@ contract KernelTest is Test { abi.encodePacked(address(callee), abi.encodeWithSelector(MockCallee.foo.selector)) ); } + + bytes32 internal constant _DOMAIN_SEP_B = + 0xa1a044077d7677adbbfa892ded5390979b33993e0e2a457e3f974bbcda53821b; + + function _erc1271Signature( + bytes32 hash, + bytes memory contentsType, + bytes memory contentsName, + function(bytes32, bool) returns(bytes memory) signFn, + bool isExplicit, + bool success + ) internal returns(bytes32 contentsHash, bytes memory sig){ + + contentsHash = keccak256(abi.encode(hash, contentsType)); + bytes32 actualHash; + if (isExplicit) { + actualHash = _toERC1271Hash(address(kernel), contentsHash, contentsType, contentsName); + } else { + actualHash = _toERC1271Hash(address(kernel), contentsHash, contentsType, _contentsName(contentsType)); + } + sig = signFn(actualHash, success); + bytes memory contentsDescription = abi.encodePacked(contentsType, contentsName); + + sig = abi.encodePacked( + sig, + _DOMAIN_SEP_B, + contentsHash, + contentsDescription, + uint16(contentsDescription.length) + ); + } + + function _toERC1271Hash( + address account, + bytes32 contents, + bytes memory contentsType, + bytes memory contentsName + ) internal view returns (bytes32) { + bytes32 parentStructHash = keccak256( + abi.encodePacked( + abi.encode(_typedDataSignTypeHash(contentsType, contentsName), contents), + _accountDomainStructFields(account) + ) + ); + return keccak256(abi.encodePacked("\x19\x01", _DOMAIN_SEP_B, parentStructHash)); + } + + struct _AccountDomainStruct { + string name; + string version; + uint256 chainId; + address verifyingContract; + bytes32 salt; + } + + + function _toContentsHash(bytes32 contents) internal pure returns (bytes32) { + return keccak256(abi.encodePacked(hex"1901", _DOMAIN_SEP_B, contents)); + } + + function _accountDomainStructFields(address account) internal view returns (bytes memory) { + _AccountDomainStruct memory t; + (, t.name, t.version, t.chainId, t.verifyingContract, t.salt,) = + kernel.eip712Domain(); + + return abi.encode( + keccak256(bytes(t.name)), + keccak256(bytes(t.version)), + t.chainId, + t.verifyingContract, + t.salt + ); + } + + function _typedDataSignTypeHash(bytes memory contentsType, bytes memory contentsName) + internal + pure + returns (bytes32) + { + return keccak256( + abi.encodePacked( + "TypedDataSign(", + contentsName, + " contents,string name,string version,uint256 chainId,address verifyingContract,bytes32 salt)", + contentsType + ) + ); + } + + function _contentsName(bytes memory contentsType) internal pure returns (bytes memory) { + string memory ct = string(contentsType); + return bytes(LibString.slice(ct, 0, LibString.indexOf(ct, "(", 0))); + } } From a76e494dfbe952f4e0d3557fa9b3af450e8fd220 Mon Sep 17 00:00:00 2001 From: leekt Date: Wed, 28 May 2025 22:40:16 +0900 Subject: [PATCH 029/121] personal sign done --- test/Kernel.t.sol | 55 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 46 insertions(+), 9 deletions(-) diff --git a/test/Kernel.t.sol b/test/Kernel.t.sol index 54fa03e9..e2fe6750 100644 --- a/test/Kernel.t.sol +++ b/test/Kernel.t.sol @@ -745,16 +745,18 @@ contract KernelTest is Test { assertEq(address(uint160(uint256(impl))), address(newTemplate)); } + + function test_erc7739() public { + assertEq( + kernel.isValidSignature( + 0x7739773977397739773977397739773977397739773977397739773977397739, "" + ), + bytes4(0x77390001) + ); + } + function test_erc1271_root() external { bytes32 messageHash = keccak256("Hello world"); - //function _erc1271Signature( - // bytes32 hash, - // bytes memory contentsType, - // bytes memory contentsName, - // function(bytes32, bool) returns(bytes memory) signFn, - // bool isExplicit, - // bool success - //) internal returns(bytes memory sig){ (bytes32 contentsHash, bytes memory sig) = _erc1271Signature(messageHash,"C(bytes32 stuff)", "", _rootSignHash, false, true); bytes4 ret = kernel.isValidSignature( @@ -762,6 +764,19 @@ contract KernelTest is Test { ); assertEq(ret, ERC1271_MAGICVALUE); } + + function test_erc1271_root_personal_sign() external { + bytes32 messageHash = keccak256("Hello world"); + bytes32 personalHash = _toERC1271HashPersonalSign(messageHash); + console.log("PersonalSig Hash :"); + console.logBytes32(personalHash); + + bytes memory sig = _rootSignHash(personalHash, true); + bytes4 ret = kernel.isValidSignature( + messageHash, abi.encodePacked(bytes20(0), sig) + ); + assertEq(ret, ERC1271_MAGICVALUE); + } function test_install_invalid() external unitTest { MockHook mockHook = new MockHook(); @@ -1176,7 +1191,8 @@ contract KernelTest is Test { abi.encodePacked(address(callee), abi.encodeWithSelector(MockCallee.foo.selector)) ); } - + + // Code heavily inspired by solady's erc1271, erc4337 test file bytes32 internal constant _DOMAIN_SEP_B = 0xa1a044077d7677adbbfa892ded5390979b33993e0e2a457e3f974bbcda53821b; @@ -1249,6 +1265,27 @@ contract KernelTest is Test { t.salt ); } + + function _toERC1271HashPersonalSign(bytes32 childHash) internal view returns (bytes32) { + _AccountDomainStruct memory t; + (, t.name, t.version, t.chainId, t.verifyingContract, t.salt,) = + kernel.eip712Domain(); + + bytes32 domainSeparator = keccak256( + abi.encode( + keccak256( + "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" + ), + keccak256(abi.encodePacked(t.name)), + keccak256(abi.encodePacked(t.version)), + t.chainId, + t.verifyingContract + ) + ); + bytes32 parentStructHash = + keccak256(abi.encode(keccak256("PersonalSign(bytes prefixed)"), childHash)); + return keccak256(abi.encodePacked("\x19\x01", domainSeparator, parentStructHash)); + } function _typedDataSignTypeHash(bytes memory contentsType, bytes memory contentsName) internal From d8c959ced0980f46ab6ac2f3b28f08d17022f0a7 Mon Sep 17 00:00:00 2001 From: leekt Date: Wed, 28 May 2025 22:40:40 +0900 Subject: [PATCH 030/121] fmt --- src/core/ModuleManager.sol | 11 ++---- test/Kernel.t.sol | 80 +++++++++++++------------------------- 2 files changed, 30 insertions(+), 61 deletions(-) diff --git a/src/core/ModuleManager.sol b/src/core/ModuleManager.sol index e130bbbf..cf1da146 100644 --- a/src/core/ModuleManager.sol +++ b/src/core/ModuleManager.sol @@ -41,13 +41,8 @@ abstract contract ModuleManager is ValidationManager, ExecutorManager, HookManag function _erc1271Signer() internal view override returns (address) { return address(1); } - - function _erc1271IsValidSignature(bytes32 hash, bytes calldata signature) - internal - view - override - returns (bool) - { + + function _erc1271IsValidSignature(bytes32 hash, bytes calldata signature) internal view override returns (bool) { return _erc1271IsValidSignatureViaNestedEIP712(hash, signature); } @@ -58,7 +53,7 @@ abstract contract ModuleManager is ValidationManager, ExecutorManager, HookManag returns (bool) { ValidationId vId = ValidationId.wrap(bytes20(signature[0:20])); - if(vId == ValidationId.wrap(bytes20(0))){ + if (vId == ValidationId.wrap(bytes20(0))) { vId = _validationStorage().root; } uint256 validationData = _verifySignature(vId, msg.sender, hash, signature[20:]); diff --git a/test/Kernel.t.sol b/test/Kernel.t.sol index e2fe6750..2ab6695f 100644 --- a/test/Kernel.t.sol +++ b/test/Kernel.t.sol @@ -745,12 +745,9 @@ contract KernelTest is Test { assertEq(address(uint160(uint256(impl))), address(newTemplate)); } - function test_erc7739() public { assertEq( - kernel.isValidSignature( - 0x7739773977397739773977397739773977397739773977397739773977397739, "" - ), + kernel.isValidSignature(0x7739773977397739773977397739773977397739773977397739773977397739, ""), bytes4(0x77390001) ); } @@ -758,13 +755,12 @@ contract KernelTest is Test { function test_erc1271_root() external { bytes32 messageHash = keccak256("Hello world"); - (bytes32 contentsHash, bytes memory sig) = _erc1271Signature(messageHash,"C(bytes32 stuff)", "", _rootSignHash, false, true); - bytes4 ret = kernel.isValidSignature( - _toContentsHash(contentsHash), abi.encodePacked(bytes20(0), sig ) - ); + (bytes32 contentsHash, bytes memory sig) = + _erc1271Signature(messageHash, "C(bytes32 stuff)", "", _rootSignHash, false, true); + bytes4 ret = kernel.isValidSignature(_toContentsHash(contentsHash), abi.encodePacked(bytes20(0), sig)); assertEq(ret, ERC1271_MAGICVALUE); } - + function test_erc1271_root_personal_sign() external { bytes32 messageHash = keccak256("Hello world"); bytes32 personalHash = _toERC1271HashPersonalSign(messageHash); @@ -772,9 +768,7 @@ contract KernelTest is Test { console.logBytes32(personalHash); bytes memory sig = _rootSignHash(personalHash, true); - bytes4 ret = kernel.isValidSignature( - messageHash, abi.encodePacked(bytes20(0), sig) - ); + bytes4 ret = kernel.isValidSignature(messageHash, abi.encodePacked(bytes20(0), sig)); assertEq(ret, ERC1271_MAGICVALUE); } @@ -1193,9 +1187,8 @@ contract KernelTest is Test { } // Code heavily inspired by solady's erc1271, erc4337 test file - bytes32 internal constant _DOMAIN_SEP_B = - 0xa1a044077d7677adbbfa892ded5390979b33993e0e2a457e3f974bbcda53821b; - + bytes32 internal constant _DOMAIN_SEP_B = 0xa1a044077d7677adbbfa892ded5390979b33993e0e2a457e3f974bbcda53821b; + function _erc1271Signature( bytes32 hash, bytes memory contentsType, @@ -1203,8 +1196,7 @@ contract KernelTest is Test { function(bytes32, bool) returns(bytes memory) signFn, bool isExplicit, bool success - ) internal returns(bytes32 contentsHash, bytes memory sig){ - + ) internal returns (bytes32 contentsHash, bytes memory sig) { contentsHash = keccak256(abi.encode(hash, contentsType)); bytes32 actualHash; if (isExplicit) { @@ -1215,21 +1207,15 @@ contract KernelTest is Test { sig = signFn(actualHash, success); bytes memory contentsDescription = abi.encodePacked(contentsType, contentsName); - sig = abi.encodePacked( - sig, - _DOMAIN_SEP_B, - contentsHash, - contentsDescription, - uint16(contentsDescription.length) - ); + sig = + abi.encodePacked(sig, _DOMAIN_SEP_B, contentsHash, contentsDescription, uint16(contentsDescription.length)); } - - function _toERC1271Hash( - address account, - bytes32 contents, - bytes memory contentsType, - bytes memory contentsName - ) internal view returns (bytes32) { + + function _toERC1271Hash(address account, bytes32 contents, bytes memory contentsType, bytes memory contentsName) + internal + view + returns (bytes32) + { bytes32 parentStructHash = keccak256( abi.encodePacked( abi.encode(_typedDataSignTypeHash(contentsType, contentsName), contents), @@ -1238,7 +1224,7 @@ contract KernelTest is Test { ); return keccak256(abi.encodePacked("\x19\x01", _DOMAIN_SEP_B, parentStructHash)); } - + struct _AccountDomainStruct { string name; string version; @@ -1247,46 +1233,34 @@ contract KernelTest is Test { bytes32 salt; } - function _toContentsHash(bytes32 contents) internal pure returns (bytes32) { return keccak256(abi.encodePacked(hex"1901", _DOMAIN_SEP_B, contents)); } - + function _accountDomainStructFields(address account) internal view returns (bytes memory) { _AccountDomainStruct memory t; - (, t.name, t.version, t.chainId, t.verifyingContract, t.salt,) = - kernel.eip712Domain(); - - return abi.encode( - keccak256(bytes(t.name)), - keccak256(bytes(t.version)), - t.chainId, - t.verifyingContract, - t.salt - ); + (, t.name, t.version, t.chainId, t.verifyingContract, t.salt,) = kernel.eip712Domain(); + + return abi.encode(keccak256(bytes(t.name)), keccak256(bytes(t.version)), t.chainId, t.verifyingContract, t.salt); } function _toERC1271HashPersonalSign(bytes32 childHash) internal view returns (bytes32) { _AccountDomainStruct memory t; - (, t.name, t.version, t.chainId, t.verifyingContract, t.salt,) = - kernel.eip712Domain(); + (, t.name, t.version, t.chainId, t.verifyingContract, t.salt,) = kernel.eip712Domain(); bytes32 domainSeparator = keccak256( abi.encode( - keccak256( - "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" - ), + keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), keccak256(abi.encodePacked(t.name)), keccak256(abi.encodePacked(t.version)), t.chainId, t.verifyingContract ) ); - bytes32 parentStructHash = - keccak256(abi.encode(keccak256("PersonalSign(bytes prefixed)"), childHash)); + bytes32 parentStructHash = keccak256(abi.encode(keccak256("PersonalSign(bytes prefixed)"), childHash)); return keccak256(abi.encodePacked("\x19\x01", domainSeparator, parentStructHash)); } - + function _typedDataSignTypeHash(bytes memory contentsType, bytes memory contentsName) internal pure @@ -1301,7 +1275,7 @@ contract KernelTest is Test { ) ); } - + function _contentsName(bytes memory contentsType) internal pure returns (bytes memory) { string memory ct = string(contentsType); return bytes(LibString.slice(ct, 0, LibString.indexOf(ct, "(", 0))); From 611b1d07fd6029970d9984418cc717659ad97835 Mon Sep 17 00:00:00 2001 From: leekt Date: Wed, 28 May 2025 23:03:01 +0900 Subject: [PATCH 031/121] erc1271 tests --- test/Kernel.t.sol | 131 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 124 insertions(+), 7 deletions(-) diff --git a/test/Kernel.t.sol b/test/Kernel.t.sol index 2ab6695f..99387406 100644 --- a/test/Kernel.t.sol +++ b/test/Kernel.t.sol @@ -175,8 +175,12 @@ contract KernelTest is Test { bytes[] memory signatures = new bytes[](2); signatures[0] = hex"dead"; signatures[1] = hex"beef"; + if (success || permissionRevertIndex != 0) { policy.sudoSetPass(address(kernel), permissionId, true); + } + if (success || permissionRevertIndex != 1) { signer.sudoSetPass(address(kernel), permissionId, true); + } return abi.encode(signatures); } @@ -654,12 +658,37 @@ contract KernelTest is Test { ep.handleOps(ops, beneficiary); } - function test_deploy() external unitTest { + function test_deploy_root_validator() external unitTest { vm.skip(is7702); Install[] memory pkgs = new Install[](1); pkgs[0] = Install({moduleType: 1, module: address(mockValidator), moduleData: hex"", internalData: hex""}); Kernel k = factory.deploy(pkgs, 1); } + + function test_deploy_root_permission() external unitTest { + Install[] memory pkgs = new Install[](2); + pkgs[0] = Install({ + moduleType: 5, + module: address(policy), + internalData: abi.encodePacked(permissionId), + moduleData: hex"" + }); + pkgs[1] = Install({moduleType: 1, module: address(newValidator), internalData: hex"", moduleData: hex""}); + Kernel k = factory.deploy(pkgs, 1); + } + + function test_deploy_root_fail_invalid_root() external unitTest { + Install[] memory pkgs = new Install[](2); + pkgs[0] = Install({ + moduleType: 2, + module: address(executor), + internalData: hex"", + moduleData: hex"" + }); + pkgs[1] = Install({moduleType: 1, module: address(newValidator), internalData: hex"", moduleData: hex""}); + vm.expectRevert(InvalidRootValidation.selector); + Kernel k = factory.deploy(pkgs, 1); + } function test_deploy_existing() external { vm.skip(is7702); @@ -752,26 +781,114 @@ contract KernelTest is Test { ); } - function test_erc1271_root() external { + function test_erc1271_root() external unitTest { bytes32 messageHash = keccak256("Hello world"); - (bytes32 contentsHash, bytes memory sig) = _erc1271Signature(messageHash, "C(bytes32 stuff)", "", _rootSignHash, false, true); bytes4 ret = kernel.isValidSignature(_toContentsHash(contentsHash), abi.encodePacked(bytes20(0), sig)); assertEq(ret, ERC1271_MAGICVALUE); } + + function test_erc1271_root_fail() external unitTest { + bytes32 messageHash = keccak256("Hello world"); + (bytes32 contentsHash, bytes memory sig) = + _erc1271Signature(messageHash, "C(bytes32 stuff)", "", _rootSignHash, false, false); + bytes4 ret = kernel.isValidSignature(_toContentsHash(contentsHash), abi.encodePacked(bytes20(0), sig)); + assertEq(ret, ERC1271_INVALID); + } - function test_erc1271_root_personal_sign() external { + function test_erc1271_root_personal_sign() external unitTest { bytes32 messageHash = keccak256("Hello world"); bytes32 personalHash = _toERC1271HashPersonalSign(messageHash); - console.log("PersonalSig Hash :"); - console.logBytes32(personalHash); - bytes memory sig = _rootSignHash(personalHash, true); bytes4 ret = kernel.isValidSignature(messageHash, abi.encodePacked(bytes20(0), sig)); assertEq(ret, ERC1271_MAGICVALUE); } + function test_erc1271_root_personal_sign_fail() external unitTest { + bytes32 messageHash = keccak256("Hello world"); + bytes32 personalHash = _toERC1271HashPersonalSign(messageHash); + bytes memory sig = _rootSignHash(personalHash, false); + bytes4 ret = kernel.isValidSignature(messageHash, abi.encodePacked(bytes20(0), sig)); + assertEq(ret, ERC1271_INVALID); + } + + function test_erc1271_validator() external unitTest { + bytes32 messageHash = keccak256("Hello world"); + (bytes32 contentsHash, bytes memory sig) = + _erc1271Signature(messageHash, "C(bytes32 stuff)", "", _validatorSignHash, false, true); + kernel.installModule(1, address(newValidator), abi.encode(hex"", hex"")); + bytes4 ret = kernel.isValidSignature(_toContentsHash(contentsHash), abi.encodePacked(bytes20(address(newValidator)), sig)); + assertEq(ret, ERC1271_MAGICVALUE); + } + + function test_erc1271_validator_fail() external unitTest { + bytes32 messageHash = keccak256("Hello world"); + (bytes32 contentsHash, bytes memory sig) = + _erc1271Signature(messageHash, "C(bytes32 stuff)", "", _validatorSignHash, false, false); + kernel.installModule(1, address(newValidator), abi.encode(hex"", hex"")); + bytes4 ret = kernel.isValidSignature(_toContentsHash(contentsHash), abi.encodePacked(bytes20(address(newValidator)), sig)); + assertEq(ret, ERC1271_INVALID); + } + + function test_erc1271_validator_personal_sign() external unitTest{ + bytes32 messageHash = keccak256("Hello world"); + bytes32 personalHash = _toERC1271HashPersonalSign(messageHash); + bytes memory sig = _validatorSignHash(personalHash, true); + kernel.installModule(1, address(newValidator), abi.encode(hex"", hex"")); + bytes4 ret = kernel.isValidSignature(messageHash, abi.encodePacked(bytes20(address(newValidator)), sig)); + assertEq(ret, ERC1271_MAGICVALUE); + } + + function test_erc1271_validator_personal_sign_fail() external unitTest{ + bytes32 messageHash = keccak256("Hello world"); + bytes32 personalHash = _toERC1271HashPersonalSign(messageHash); + bytes memory sig = _validatorSignHash(personalHash, false); + kernel.installModule(1, address(newValidator), abi.encode(hex"", hex"")); + bytes4 ret = kernel.isValidSignature(messageHash, abi.encodePacked(bytes20(address(newValidator)), sig)); + assertEq(ret, ERC1271_INVALID); + } + + function test_erc1271_permission() external unitTest { + bytes32 messageHash = keccak256("Hello world"); + (bytes32 contentsHash, bytes memory sig) = + _erc1271Signature(messageHash, "C(bytes32 stuff)", "", _permissionSignHash, false, true); + kernel.installModule(5, address(policy), abi.encode(hex"deadbeef", abi.encodePacked(permissionId))); + kernel.installModule(6, address(signer), abi.encode(hex"deadbeef", abi.encodePacked(permissionId))); + bytes4 ret = kernel.isValidSignature(_toContentsHash(contentsHash), abi.encodePacked(permissionId, sig)); + assertEq(ret, ERC1271_MAGICVALUE); + } + + function test_erc1271_permission_fail() external unitTest { + bytes32 messageHash = keccak256("Hello world"); + (bytes32 contentsHash, bytes memory sig) = + _erc1271Signature(messageHash, "C(bytes32 stuff)", "", _permissionSignHash, false, false); + kernel.installModule(5, address(policy), abi.encode(hex"deadbeef", abi.encodePacked(permissionId))); + kernel.installModule(6, address(signer), abi.encode(hex"deadbeef", abi.encodePacked(permissionId))); + bytes4 ret = kernel.isValidSignature(_toContentsHash(contentsHash), abi.encodePacked(permissionId, sig)); + assertEq(ret, ERC1271_INVALID); + } + + function test_erc1271_permission_personal_sign() external unitTest{ + bytes32 messageHash = keccak256("Hello world"); + bytes32 personalHash = _toERC1271HashPersonalSign(messageHash); + bytes memory sig = _permissionSignHash(personalHash, true); + kernel.installModule(5, address(policy), abi.encode(hex"deadbeef", abi.encodePacked(permissionId))); + kernel.installModule(6, address(signer), abi.encode(hex"deadbeef", abi.encodePacked(permissionId))); + bytes4 ret = kernel.isValidSignature(messageHash, abi.encodePacked(permissionId, sig)); + assertEq(ret, ERC1271_MAGICVALUE); + } + + function test_erc1271_permission_personal_sign_fail() external unitTest{ + bytes32 messageHash = keccak256("Hello world"); + bytes32 personalHash = _toERC1271HashPersonalSign(messageHash); + bytes memory sig = _permissionSignHash(personalHash, false); + kernel.installModule(5, address(policy), abi.encode(hex"deadbeef", abi.encodePacked(permissionId))); + kernel.installModule(6, address(signer), abi.encode(hex"deadbeef", abi.encodePacked(permissionId))); + bytes4 ret = kernel.isValidSignature(messageHash, abi.encodePacked(permissionId, sig)); + assertEq(ret, ERC1271_INVALID); + } + function test_install_invalid() external unitTest { MockHook mockHook = new MockHook(); vm.expectRevert(NotImplemented.selector); From c63e35b586ad5dac6abb40282ee93abf265042e5 Mon Sep 17 00:00:00 2001 From: leekt Date: Wed, 28 May 2025 23:03:13 +0900 Subject: [PATCH 032/121] fmt --- test/Kernel.t.sol | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/test/Kernel.t.sol b/test/Kernel.t.sol index 99387406..b9a36644 100644 --- a/test/Kernel.t.sol +++ b/test/Kernel.t.sol @@ -176,10 +176,10 @@ contract KernelTest is Test { signatures[0] = hex"dead"; signatures[1] = hex"beef"; if (success || permissionRevertIndex != 0) { - policy.sudoSetPass(address(kernel), permissionId, true); + policy.sudoSetPass(address(kernel), permissionId, true); } if (success || permissionRevertIndex != 1) { - signer.sudoSetPass(address(kernel), permissionId, true); + signer.sudoSetPass(address(kernel), permissionId, true); } return abi.encode(signatures); @@ -664,7 +664,7 @@ contract KernelTest is Test { pkgs[0] = Install({moduleType: 1, module: address(mockValidator), moduleData: hex"", internalData: hex""}); Kernel k = factory.deploy(pkgs, 1); } - + function test_deploy_root_permission() external unitTest { Install[] memory pkgs = new Install[](2); pkgs[0] = Install({ @@ -676,15 +676,10 @@ contract KernelTest is Test { pkgs[1] = Install({moduleType: 1, module: address(newValidator), internalData: hex"", moduleData: hex""}); Kernel k = factory.deploy(pkgs, 1); } - + function test_deploy_root_fail_invalid_root() external unitTest { Install[] memory pkgs = new Install[](2); - pkgs[0] = Install({ - moduleType: 2, - module: address(executor), - internalData: hex"", - moduleData: hex"" - }); + pkgs[0] = Install({moduleType: 2, module: address(executor), internalData: hex"", moduleData: hex""}); pkgs[1] = Install({moduleType: 1, module: address(newValidator), internalData: hex"", moduleData: hex""}); vm.expectRevert(InvalidRootValidation.selector); Kernel k = factory.deploy(pkgs, 1); @@ -788,7 +783,7 @@ contract KernelTest is Test { bytes4 ret = kernel.isValidSignature(_toContentsHash(contentsHash), abi.encodePacked(bytes20(0), sig)); assertEq(ret, ERC1271_MAGICVALUE); } - + function test_erc1271_root_fail() external unitTest { bytes32 messageHash = keccak256("Hello world"); (bytes32 contentsHash, bytes memory sig) = @@ -818,7 +813,9 @@ contract KernelTest is Test { (bytes32 contentsHash, bytes memory sig) = _erc1271Signature(messageHash, "C(bytes32 stuff)", "", _validatorSignHash, false, true); kernel.installModule(1, address(newValidator), abi.encode(hex"", hex"")); - bytes4 ret = kernel.isValidSignature(_toContentsHash(contentsHash), abi.encodePacked(bytes20(address(newValidator)), sig)); + bytes4 ret = kernel.isValidSignature( + _toContentsHash(contentsHash), abi.encodePacked(bytes20(address(newValidator)), sig) + ); assertEq(ret, ERC1271_MAGICVALUE); } @@ -827,11 +824,13 @@ contract KernelTest is Test { (bytes32 contentsHash, bytes memory sig) = _erc1271Signature(messageHash, "C(bytes32 stuff)", "", _validatorSignHash, false, false); kernel.installModule(1, address(newValidator), abi.encode(hex"", hex"")); - bytes4 ret = kernel.isValidSignature(_toContentsHash(contentsHash), abi.encodePacked(bytes20(address(newValidator)), sig)); + bytes4 ret = kernel.isValidSignature( + _toContentsHash(contentsHash), abi.encodePacked(bytes20(address(newValidator)), sig) + ); assertEq(ret, ERC1271_INVALID); } - function test_erc1271_validator_personal_sign() external unitTest{ + function test_erc1271_validator_personal_sign() external unitTest { bytes32 messageHash = keccak256("Hello world"); bytes32 personalHash = _toERC1271HashPersonalSign(messageHash); bytes memory sig = _validatorSignHash(personalHash, true); @@ -840,7 +839,7 @@ contract KernelTest is Test { assertEq(ret, ERC1271_MAGICVALUE); } - function test_erc1271_validator_personal_sign_fail() external unitTest{ + function test_erc1271_validator_personal_sign_fail() external unitTest { bytes32 messageHash = keccak256("Hello world"); bytes32 personalHash = _toERC1271HashPersonalSign(messageHash); bytes memory sig = _validatorSignHash(personalHash, false); @@ -869,7 +868,7 @@ contract KernelTest is Test { assertEq(ret, ERC1271_INVALID); } - function test_erc1271_permission_personal_sign() external unitTest{ + function test_erc1271_permission_personal_sign() external unitTest { bytes32 messageHash = keccak256("Hello world"); bytes32 personalHash = _toERC1271HashPersonalSign(messageHash); bytes memory sig = _permissionSignHash(personalHash, true); @@ -879,7 +878,7 @@ contract KernelTest is Test { assertEq(ret, ERC1271_MAGICVALUE); } - function test_erc1271_permission_personal_sign_fail() external unitTest{ + function test_erc1271_permission_personal_sign_fail() external unitTest { bytes32 messageHash = keccak256("Hello world"); bytes32 personalHash = _toERC1271HashPersonalSign(messageHash); bytes memory sig = _permissionSignHash(personalHash, false); From 8504a5fae22dbadd470e3e152febfe1d48642d26 Mon Sep 17 00:00:00 2001 From: leekt Date: Wed, 28 May 2025 23:17:17 +0900 Subject: [PATCH 033/121] erc1271 replayable --- test/Kernel.t.sol | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/test/Kernel.t.sol b/test/Kernel.t.sol index b9a36644..b1a3d4e2 100644 --- a/test/Kernel.t.sol +++ b/test/Kernel.t.sol @@ -748,6 +748,18 @@ contract KernelTest is Test { kernel.installModule(false, 0, packages, enableSig(0, true, false, packages, _rootSignHash)); } + function test_install_packages_with_signature_replayable() external unitTest { + Install[] memory packages = new Install[](2); + packages[0] = Install({moduleType: 1, module: address(newValidator), internalData: hex"", moduleData: hex""}); + packages[1] = Install({ + moduleType: 5, + module: address(policy), + internalData: abi.encodePacked(permissionId), + moduleData: hex"" + }); + kernel.installModule(true, 0, packages, enableSig(0, true, true, packages, _rootSignHash)); + } + function test_change_root() external unitTest { Install[] memory packages = new Install[](2); packages[0] = Install({moduleType: 1, module: address(newValidator), internalData: hex"", moduleData: hex""}); @@ -776,6 +788,15 @@ contract KernelTest is Test { ); } + function test_erc1271_fail_invalid() external unitTest { + bytes32 messageHash = keccak256("Hello world"); + (bytes32 contentsHash, bytes memory sig) = + _erc1271Signature(messageHash, "C(bytes32 stuff)", "", _rootSignHash, false, true); + bytes4 ret = + kernel.isValidSignature(_toContentsHash(contentsHash), abi.encodePacked(bytes20(address(this)), sig)); + assertEq(ret, ERC1271_INVALID); + } + function test_erc1271_root() external unitTest { bytes32 messageHash = keccak256("Hello world"); (bytes32 contentsHash, bytes memory sig) = From 1c36237ea782e233d67f0a63e56c38d9b29e3083 Mon Sep 17 00:00:00 2001 From: leekt Date: Wed, 28 May 2025 23:39:35 +0900 Subject: [PATCH 034/121] readme update --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 50b34cdb..64276ab3 100644 --- a/README.md +++ b/README.md @@ -13,14 +13,15 @@ open coverage/index.html - Testing - [ ] certora testing - [ ] unit test coverage 100% + - almost? - [ ] halmos testing ## Kernel V4 - [x] native v0.8 support - [x] factory update, needs to consider 7702 context - [x] eip712 userOpHash support -- [ ] native 7702 support - - test +- [x] native 7702 support + - [x] test - [x] 7579 account - [x] erc7821 execute interface - [x] execute with signature From 60fe5e5160eaf16b409d24e6692766cdfc1699c2 Mon Sep 17 00:00:00 2001 From: leekt Date: Thu, 29 May 2025 03:33:56 +0900 Subject: [PATCH 035/121] feat: added nonce invalidation feature --- src/Kernel.sol | 20 ++++++++--- src/core/ModuleManager.sol | 52 +++++++++++++++++++++++----- test/Kernel.t.sol | 69 ++++++++++++++++++++++++++++++++++---- 3 files changed, 122 insertions(+), 19 deletions(-) diff --git a/src/Kernel.sol b/src/Kernel.sol index 8f3fc72c..7118ed1b 100644 --- a/src/Kernel.sol +++ b/src/Kernel.sol @@ -210,13 +210,15 @@ contract Kernel is ModuleManager, ExecutionManager, UUPSUpgradeable { function supportsExecutionMode(bytes32 mode) external view returns (bool) { bytes1 callType = LibERC7579.getCallType(mode); bytes1 execType = LibERC7579.getExecType(mode); - if (execType == LibERC7579.EXECTYPE_DEFAULT || execType == LibERC7579.EXECTYPE_TRY) {} else { + if (!(execType == LibERC7579.EXECTYPE_DEFAULT || execType == LibERC7579.EXECTYPE_TRY)) { return false; } if ( - callType == LibERC7579.CALLTYPE_SINGLE || callType == LibERC7579.CALLTYPE_BATCH - || callType == LibERC7579.CALLTYPE_DELEGATECALL - ) {} else { + !( + callType == LibERC7579.CALLTYPE_SINGLE || callType == LibERC7579.CALLTYPE_BATCH + || callType == LibERC7579.CALLTYPE_DELEGATECALL + ) + ) { return false; } return true; @@ -262,4 +264,14 @@ contract Kernel is ModuleManager, ExecutionManager, UUPSUpgradeable { function accountId() external view returns (string memory accountImplementationId) { return "kernel.v0.4"; } + + function setNonce(uint192 nonceKey, uint64 seq) external { + _onlyEntryPointOrSelf(); + _setNonce(nonceKey, seq); + } + + function setValidNonceFrom(uint64 seq) external { + _onlyEntryPointOrSelf(); + _setValidNonceFrom(seq); + } } diff --git a/src/core/ModuleManager.sol b/src/core/ModuleManager.sol index cf1da146..35cafe5d 100644 --- a/src/core/ModuleManager.sol +++ b/src/core/ModuleManager.sol @@ -15,6 +15,7 @@ import "../lib/Utils.sol"; import "../lib/Lib4337.sol"; struct ModuleStorage { + address registry; // Note : not used on vanila kernel but saving the storage slot for future usage uint64 nonceValidFrom; mapping(uint192 key => uint64) nonce; } @@ -27,6 +28,27 @@ abstract contract ModuleManager is ValidationManager, ExecutorManager, HookManag _postHook(hook, hookData); } + // NOTE : override this to use erc7484 registry + modifier installModuleHook(uint256 moduleType, address module) virtual { + _; + } + + function registry() external view returns (address) { + return _moduleStorage().registry; + } + + function validNonceFrom() external view returns (uint64) { + return _moduleStorage().nonceValidFrom; + } + + function nonce(uint192 key) external view returns (uint256) { + uint64 seq = _moduleStorage().nonce[key]; + if(_moduleStorage().nonceValidFrom > seq) { + seq = _moduleStorage().nonceValidFrom; + } + return (uint256(key) << 64) + seq; + } + function _initialized() internal view returns (bool) { return bytes3(address(this).code) == bytes3(0xef0100) || ValidationId.unwrap(_validationStorage().root) != bytes20(0); @@ -81,6 +103,7 @@ abstract contract ModuleManager is ValidationManager, ExecutorManager, HookManag function _installModule(uint256 moduleType, address module, bytes calldata moduleData, bytes calldata internalData) internal + installModuleHook(moduleType, module) { function(address, bytes calldata, bool) hook; if (moduleType == 1) { @@ -159,37 +182,50 @@ abstract contract ModuleManager is ValidationManager, ExecutorManager, HookManag function _verifyInstallSignature( bool replayable, - uint256 nonce, + uint256 _nonce, Install[] calldata packages, bytes calldata signature ) internal returns (bool success) { - uint256 validationData = _verifyInstallSignatureRaw(replayable, nonce, packages, signature); + uint256 validationData = _verifyInstallSignatureRaw(replayable, _nonce, packages, signature); return Lib4337.checkValidation(validationData); } - function _checkNonce(uint256 nonce) internal virtual returns (bool) { - uint192 key = uint192(nonce >> 64); - uint64 seq = uint64(nonce); + function _setValidNonceFrom(uint64 nonceFrom) internal { + require(nonceFrom > _moduleStorage().nonceValidFrom, InvalidNonce()); + _moduleStorage().nonceValidFrom = nonceFrom; + } + + function _setNonce(uint192 nonceKey, uint64 seq) internal { + require(seq > _moduleStorage().nonce[nonceKey], InvalidNonce()); + _moduleStorage().nonce[nonceKey] = seq; + } + + function _checkNonce(uint256 _nonce) internal virtual returns (bool) { + uint192 key = uint192(_nonce >> 64); + uint64 seq = uint64(_nonce); + if (_moduleStorage().nonceValidFrom > _moduleStorage().nonce[key]) { + _moduleStorage().nonce[key] = _moduleStorage().nonceValidFrom; + } return _moduleStorage().nonce[key]++ == seq; } function _verifyInstallSignatureRaw( bool replayable, - uint256 nonce, + uint256 _nonce, Install[] calldata packages, bytes calldata signature ) internal returns (uint256 validationData) { ValidationId vId = _validationStorage().root; function(bytes32) internal view returns(bytes32) hashTypedData = replayable ? _hashTypedDataSansChainId : _hashTypedData; - require(_checkNonce(nonce), InvalidNonce()); + require(_checkNonce(_nonce), InvalidNonce()); bytes32 digest = hashTypedData( keccak256( abi.encode( keccak256( "InstallPackages(uint256 nonce,Install[] packages)Install(uint256 moduleType,address module,bytes moduleData,bytes internalData)" ), - nonce, + _nonce, _installHash(packages) ) ) diff --git a/test/Kernel.t.sol b/test/Kernel.t.sol index b1a3d4e2..d8fa5aa1 100644 --- a/test/Kernel.t.sol +++ b/test/Kernel.t.sol @@ -675,6 +675,8 @@ contract KernelTest is Test { }); pkgs[1] = Install({moduleType: 1, module: address(newValidator), internalData: hex"", moduleData: hex""}); Kernel k = factory.deploy(pkgs, 1); + assertEq(k.accountId(), "kernel.v0.4"); + assertEq(k.registry(), address(0)); } function test_deploy_root_fail_invalid_root() external unitTest { @@ -736,6 +738,55 @@ contract KernelTest is Test { assertEq(address(kernel.executorConfig(newEx).hook), address(0)); } + function test_set_valid_nonce() external unitTest { + kernel.setValidNonceFrom(1); + assertEq(kernel.validNonceFrom(), 1); + + Install[] memory packages = new Install[](2); + packages[0] = Install({moduleType: 1, module: address(newValidator), internalData: hex"", moduleData: hex""}); + packages[1] = Install({ + moduleType: 5, + module: address(policy), + internalData: abi.encodePacked(permissionId), + moduleData: hex"" + }); + bytes memory sig = enableSig(0, true, false, packages, _rootSignHash); + vm.expectRevert(InvalidNonce.selector); + kernel.installModule(false, 0, packages, sig); + sig = enableSig(uint256(1) << 64, true, false, packages, _rootSignHash); + vm.expectRevert(InvalidNonce.selector); + kernel.installModule(false, uint256(1) << 64, packages, sig); + sig = enableSig(1, true, false, packages, _rootSignHash); + kernel.installModule(false, 1, packages, sig); + } + + function test_set_nonce() external unitTest { + kernel.setNonce(0, 1); + assertEq(kernel.nonce(0), 1); + + Install[] memory packages = new Install[](2); + packages[0] = Install({moduleType: 1, module: address(newValidator), internalData: hex"", moduleData: hex""}); + packages[1] = Install({ + moduleType: 5, + module: address(policy), + internalData: abi.encodePacked(permissionId), + moduleData: hex"" + }); + bytes memory sig = enableSig(0, true, false, packages, _rootSignHash); + vm.expectRevert(InvalidNonce.selector); + kernel.installModule(false, 0, packages, sig); + sig = enableSig(uint256(1) << 64, true, false, packages, _rootSignHash); + kernel.installModule(false, uint256(1) << 64, packages, sig); + } + + function test_set_valid_nonce_decrease_nonce() external unitTest { + kernel.setValidNonceFrom(100); + assertEq(kernel.validNonceFrom(), 100); + assertEq(kernel.nonce(0), 100); + vm.expectRevert(InvalidNonce.selector); + kernel.setValidNonceFrom(1); + } + function test_install_packages_with_signature() external unitTest { Install[] memory packages = new Install[](2); packages[0] = Install({moduleType: 1, module: address(newValidator), internalData: hex"", moduleData: hex""}); @@ -788,21 +839,21 @@ contract KernelTest is Test { ); } - function test_erc1271_fail_invalid() external unitTest { + function test_erc1271_root() external unitTest { bytes32 messageHash = keccak256("Hello world"); (bytes32 contentsHash, bytes memory sig) = _erc1271Signature(messageHash, "C(bytes32 stuff)", "", _rootSignHash, false, true); - bytes4 ret = - kernel.isValidSignature(_toContentsHash(contentsHash), abi.encodePacked(bytes20(address(this)), sig)); - assertEq(ret, ERC1271_INVALID); + bytes4 ret = kernel.isValidSignature(_toContentsHash(contentsHash), abi.encodePacked(bytes20(0), sig)); + assertEq(ret, ERC1271_MAGICVALUE); } - function test_erc1271_root() external unitTest { + function test_erc1271_fail_invalid() external unitTest { bytes32 messageHash = keccak256("Hello world"); (bytes32 contentsHash, bytes memory sig) = _erc1271Signature(messageHash, "C(bytes32 stuff)", "", _rootSignHash, false, true); - bytes4 ret = kernel.isValidSignature(_toContentsHash(contentsHash), abi.encodePacked(bytes20(0), sig)); - assertEq(ret, ERC1271_MAGICVALUE); + bytes4 ret = + kernel.isValidSignature(_toContentsHash(contentsHash), abi.encodePacked(bytes20(address(this)), sig)); + assertEq(ret, ERC1271_INVALID); } function test_erc1271_root_fail() external unitTest { @@ -913,6 +964,8 @@ contract KernelTest is Test { MockHook mockHook = new MockHook(); vm.expectRevert(NotImplemented.selector); kernel.installModule(10, address(mockHook), abi.encode(hex"", "")); + vm.expectRevert(NotImplemented.selector); + kernel.isModuleInstalled(10, address(mockHook), abi.encodePacked(permissionId)); } function test_uninstall_invalid() external unitTest { @@ -963,6 +1016,8 @@ contract KernelTest is Test { ValidationId vId = ValidationId.wrap(permissionId); ValidationInfo memory vInfo = kernel.validationInfo(vId); assertTrue(vInfo.vType == VALIDATION_TYPE_ROOT); + assertFalse(kernel.isModuleInstalled(5, address(policy), abi.encodePacked(permissionId))); + assertFalse(kernel.isModuleInstalled(6, address(signer), abi.encodePacked(permissionId))); kernel.installModule(5, address(policy), abi.encode(hex"deadbeef", abi.encodePacked(permissionId))); kernel.installModule(6, address(signer), abi.encode(hex"deadbeef", abi.encodePacked(permissionId))); bytes4 ret = kernel.isValidSignature( From a3f283834189fca4a87e4c5955a84246b7878bce Mon Sep 17 00:00:00 2001 From: leekt Date: Thu, 29 May 2025 03:34:33 +0900 Subject: [PATCH 036/121] fmt --- src/core/ModuleManager.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/ModuleManager.sol b/src/core/ModuleManager.sol index 35cafe5d..047f445d 100644 --- a/src/core/ModuleManager.sol +++ b/src/core/ModuleManager.sol @@ -43,7 +43,7 @@ abstract contract ModuleManager is ValidationManager, ExecutorManager, HookManag function nonce(uint192 key) external view returns (uint256) { uint64 seq = _moduleStorage().nonce[key]; - if(_moduleStorage().nonceValidFrom > seq) { + if (_moduleStorage().nonceValidFrom > seq) { seq = _moduleStorage().nonceValidFrom; } return (uint256(key) << 64) + seq; From 4262e35a2e29ea54366c563b8a08f5fcc5fe0d40 Mon Sep 17 00:00:00 2001 From: leekt Date: Thu, 29 May 2025 03:35:53 +0900 Subject: [PATCH 037/121] removed unused functions --- src/lib/Lib4337.sol | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/lib/Lib4337.sol b/src/lib/Lib4337.sol index ae2661bd..fd6d27e6 100644 --- a/src/lib/Lib4337.sol +++ b/src/lib/Lib4337.sol @@ -59,10 +59,6 @@ library Lib4337 { } } - function intersectValidationData(uint256 a, bytes4 res) internal pure returns (uint256) { - return _intersectValidationData(a, signatureResultToValidationData(res)); - } - function intersectValidationData(uint256 a, uint256 b) internal pure returns (uint256 validationData) { return _intersectValidationData(a, b); } @@ -99,8 +95,4 @@ library Lib4337 { default { validationData := SIG_VALIDATION_FAILED_UINT } } } - - function signatureResultToValidationData(bytes4 res) public pure returns (uint256 validationData) { - return res == ERC1271_MAGICVALUE ? 0 : 1; - } } From f82f3aebcfbbf122187090f0c67798d043a29b4d Mon Sep 17 00:00:00 2001 From: leekt Date: Thu, 29 May 2025 03:37:09 +0900 Subject: [PATCH 038/121] left comment --- src/core/ModuleManager.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/ModuleManager.sol b/src/core/ModuleManager.sol index 047f445d..1a2839fb 100644 --- a/src/core/ModuleManager.sol +++ b/src/core/ModuleManager.sol @@ -60,6 +60,7 @@ abstract contract ModuleManager is ValidationManager, ExecutorManager, HookManag } } + // NOTE: this is not accesible, but required to override because of solady's erc1271 function _erc1271Signer() internal view override returns (address) { return address(1); } From d833b240bebad058b496c970f889603f696ea6a4 Mon Sep 17 00:00:00 2001 From: leekt Date: Fri, 30 May 2025 01:30:50 +0900 Subject: [PATCH 039/121] optimizing --- snapshots/Kernel7702Test.json | 3 ++ snapshots/KernelTest.json | 3 ++ src/Kernel.sol | 9 +++--- src/core/ValidationManager.sol | 14 ++------- src/lib/Lib4337.sol | 54 ++++++++++++++++------------------ src/types/Types.sol | 36 ++++++++--------------- test/Kernel.t.sol | 2 ++ 7 files changed, 52 insertions(+), 69 deletions(-) create mode 100644 snapshots/Kernel7702Test.json create mode 100644 snapshots/KernelTest.json diff --git a/snapshots/Kernel7702Test.json b/snapshots/Kernel7702Test.json new file mode 100644 index 00000000..979b2d69 --- /dev/null +++ b/snapshots/Kernel7702Test.json @@ -0,0 +1,3 @@ +{ + "Root - foo()": "173128" +} \ No newline at end of file diff --git a/snapshots/KernelTest.json b/snapshots/KernelTest.json new file mode 100644 index 00000000..c213885d --- /dev/null +++ b/snapshots/KernelTest.json @@ -0,0 +1,3 @@ +{ + "Root - foo()": "198147" +} \ No newline at end of file diff --git a/src/Kernel.sol b/src/Kernel.sol index 7118ed1b..d1a69d36 100644 --- a/src/Kernel.sol +++ b/src/Kernel.sol @@ -47,17 +47,16 @@ contract Kernel is ModuleManager, ExecutionManager, UUPSUpgradeable { function validateUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash, uint256 missingAccountFunds) external payable - returns (uint256) + returns (uint256 validationData) { _onlyEntryPointOrSelf(); - uint256 validationData = _processUserOp(userOp, userOpHash); + validationData = _processUserOp(userOp, userOpHash); assembly { if missingAccountFunds { pop(call(gas(), caller(), missingAccountFunds, callvalue(), callvalue(), callvalue(), callvalue())) //ignore failure (its EntryPoint's job to verify, not account.) } } - return validationData; } function _processUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash) @@ -265,12 +264,12 @@ contract Kernel is ModuleManager, ExecutionManager, UUPSUpgradeable { return "kernel.v0.4"; } - function setNonce(uint192 nonceKey, uint64 seq) external { + function setNonce(uint192 nonceKey, uint64 seq) external payable { _onlyEntryPointOrSelf(); _setNonce(nonceKey, seq); } - function setValidNonceFrom(uint64 seq) external { + function setValidNonceFrom(uint64 seq) external payable { _onlyEntryPointOrSelf(); _setValidNonceFrom(seq); } diff --git a/src/core/ValidationManager.sol b/src/core/ValidationManager.sol index 00d2c889..33dd5ee2 100644 --- a/src/core/ValidationManager.sol +++ b/src/core/ValidationManager.sol @@ -10,21 +10,13 @@ import {ECDSA} from "solady/utils/ECDSA.sol"; import "forge-std/console.sol"; import {Lib4337} from "../lib/Lib4337.sol"; -function getValidator(ValidationId vId) pure returns (address v) { - assembly { - v := shr(96, vId) - } -} - function parseNonce(uint256 nonce) pure returns (ValidationMode vMode, ValidationType vType, ValidationId vId) { // 2bytes mode (1byte currentMode, 1byte type) // 20bytes identifier // 1byte mode | 1byte type | 20bytes vId | 2byte nonceKey | 8byte nonce == 32bytes - assembly { - vMode := nonce - vType := shl(8, nonce) - vId := shl(16, nonce) - } + vMode = ValidationMode.wrap(bytes1(bytes32(nonce))); + vType = ValidationType.wrap(bytes1(bytes32(nonce << 8))); + vId = ValidationId.wrap(bytes20(bytes32(nonce << 16))); } abstract contract ValidationManager { diff --git a/src/lib/Lib4337.sol b/src/lib/Lib4337.sol index fd6d27e6..2704a4dd 100644 --- a/src/lib/Lib4337.sol +++ b/src/lib/Lib4337.sol @@ -63,36 +63,32 @@ library Lib4337 { return _intersectValidationData(a, b); } - function _intersectValidationData(uint256 a, uint256 b) private pure returns (uint256 validationData) { - assembly { - // xor(a,b) == shows only matching bits - // and(xor(a,b), 0x000000000000000000000000ffffffffffffffffffffffffffffffffffffffff) == filters out the validAfter and validUntil bits - // if the result is not zero, then aggregator part is not matching - // validCase : - // a == 0 || b == 0 || xor(a,b) == 0 - // invalidCase : - // a mul b != 0 && xor(a,b) != 0 - let sum := shl(96, add(a, b)) - switch or( - iszero(and(xor(a, b), 0x000000000000000000000000ffffffffffffffffffffffffffffffffffffffff)), - or(eq(sum, shl(96, a)), eq(sum, shl(96, b))) - ) - case 1 { - validationData := and(or(a, b), 0x000000000000000000000000ffffffffffffffffffffffffffffffffffffffff) - // validAfter - let a_vd := and(0xffffffffffff0000000000000000000000000000000000000000000000000000, a) - let b_vd := and(0xffffffffffff0000000000000000000000000000000000000000000000000000, b) - validationData := or(validationData, xor(a_vd, mul(xor(a_vd, b_vd), gt(b_vd, a_vd)))) - // validUntil - a_vd := and(0x000000000000ffffffffffff0000000000000000000000000000000000000000, a) - if iszero(a_vd) { a_vd := 0x000000000000ffffffffffff0000000000000000000000000000000000000000 } - b_vd := and(0x000000000000ffffffffffff0000000000000000000000000000000000000000, b) - if iszero(b_vd) { b_vd := 0x000000000000ffffffffffff0000000000000000000000000000000000000000 } - let until := xor(a_vd, mul(xor(a_vd, b_vd), lt(b_vd, a_vd))) - if iszero(until) { until := 0x000000000000ffffffffffff0000000000000000000000000000000000000000 } - validationData := or(validationData, until) + function _intersectValidationData(uint256 preValidationData, uint256 validationRes) + private + pure + returns (uint256 resValidationData) + { + //short circuit + unchecked { + if (preValidationData * validationRes == 0) { + return preValidationData | validationRes; } - default { validationData := SIG_VALIDATION_FAILED_UINT } } + uint48 validUntil1 = uint48(preValidationData >> 160); + if (validUntil1 == 0) { + validUntil1 = type(uint48).max; + } + uint48 validUntil2 = uint48(validationRes >> 160); + if (validUntil2 == 0) { + validUntil2 = type(uint48).max; + } + resValidationData = ((validUntil1 > validUntil2) ? uint256(validUntil2) << 160 : uint256(validUntil1) << 160); + + uint48 validAfter1 = uint48(preValidationData >> 208); + uint48 validAfter2 = uint48(validationRes >> 208); + + resValidationData |= ((validAfter1 < validAfter2) ? uint256(validAfter2) << 208 : uint256(validAfter1) << 208); + + resValidationData |= uint160(preValidationData) == 1 ? 1 : uint160(validationRes); } } diff --git a/src/types/Types.sol b/src/types/Types.sol index 596c9530..1fb15f29 100644 --- a/src/types/Types.sol +++ b/src/types/Types.sol @@ -8,6 +8,18 @@ pragma solidity ^0.8.0; // _ => relayable enable signature flag type ValidationMode is bytes1; +function isEnable(ValidationMode vMode) pure returns (bool enable) { + return ValidationMode.unwrap(vMode) & bytes1(0x08) != 0; +} + +function isReplayable(ValidationMode vMode) pure returns (bool replayable) { + return ValidationMode.unwrap(vMode) & bytes1(0x40) != 0; +} + +function isEnableReplayable(ValidationMode vMode) pure returns (bool replayable) { + return ValidationMode.unwrap(vMode) & bytes1(0x04) != 0; +} + type ValidationId is bytes20; type ValidationType is bytes1; @@ -29,12 +41,6 @@ type ValidAfter is uint48; type ValidUntil is uint48; -function getValidationResult(ValidationData validationData) pure returns (address result) { - assembly { - result := validationData - } -} - function packValidationData(ValidAfter validAfter, ValidUntil validUntil) pure returns (uint256) { return uint256(ValidAfter.unwrap(validAfter)) << 208 | uint256(ValidUntil.unwrap(validUntil)) << 160; } @@ -64,21 +70,3 @@ function notEqCallType(CallType a, CallType b) pure returns (bool) { function vTypeEqual(ValidationType a, ValidationType b) pure returns (bool) { return ValidationType.unwrap(a) == ValidationType.unwrap(b); } - -function isEnable(ValidationMode vMode) pure returns (bool enable) { - assembly { - enable := iszero(iszero(and(vMode, 0x800000000000000000000000000000000000000000000000000000000000000))) - } -} - -function isReplayable(ValidationMode vMode) pure returns (bool replayable) { - assembly { - replayable := iszero(iszero(and(vMode, 0x4000000000000000000000000000000000000000000000000000000000000000))) - } -} - -function isEnableReplayable(ValidationMode vMode) pure returns (bool replayable) { - assembly { - replayable := iszero(iszero(and(vMode, 0x400000000000000000000000000000000000000000000000000000000000000))) - } -} diff --git a/test/Kernel.t.sol b/test/Kernel.t.sol index d8fa5aa1..8eb52718 100644 --- a/test/Kernel.t.sol +++ b/test/Kernel.t.sol @@ -384,7 +384,9 @@ contract KernelTest is Test { signature: hex"" }); ops[0].signature = _rootSignUserOp(ops[0], true, false); + vm.startSnapshotGas("Root - foo()"); ep.handleOps(ops, beneficiary); + vm.stopSnapshotGas(); assertEq(callee.bar(), 1); } From 7ec15c0c39aadea887be8d4f4f67e4d7d74ac836 Mon Sep 17 00:00:00 2001 From: leekt Date: Sat, 14 Jun 2025 03:02:25 +0900 Subject: [PATCH 040/121] nonce setting --- foundry.toml | 2 +- snapshots/Kernel7702Test.json | 2 +- snapshots/KernelECDSATest.json | 3 ++ snapshots/KernelTest.json | 2 +- src/Kernel.sol | 20 ++++----- test/Kernel.t.sol | 2 + test/KernelECDSA.t.sol | 37 ++++++++++++++++ test/mock/ECDSAValidator.sol | 80 ++++++++++++++++++++++++++++++++++ 8 files changed, 135 insertions(+), 13 deletions(-) create mode 100644 snapshots/KernelECDSATest.json create mode 100644 test/KernelECDSA.t.sol create mode 100644 test/mock/ECDSAValidator.sol diff --git a/foundry.toml b/foundry.toml index d3d1b49c..a5054875 100644 --- a/foundry.toml +++ b/foundry.toml @@ -2,7 +2,7 @@ src = "src" out = "out" libs = ["lib"] -via_ir = false +via_ir = true optimizer = true run = 200 evm_version = 'prague' diff --git a/snapshots/Kernel7702Test.json b/snapshots/Kernel7702Test.json index 979b2d69..d356e250 100644 --- a/snapshots/Kernel7702Test.json +++ b/snapshots/Kernel7702Test.json @@ -1,3 +1,3 @@ { - "Root - foo()": "173128" + "Root - foo()": "168761" } \ No newline at end of file diff --git a/snapshots/KernelECDSATest.json b/snapshots/KernelECDSATest.json new file mode 100644 index 00000000..7674dc2d --- /dev/null +++ b/snapshots/KernelECDSATest.json @@ -0,0 +1,3 @@ +{ + "Root - foo()": "177985" +} \ No newline at end of file diff --git a/snapshots/KernelTest.json b/snapshots/KernelTest.json index c213885d..8d68d37f 100644 --- a/snapshots/KernelTest.json +++ b/snapshots/KernelTest.json @@ -1,3 +1,3 @@ { - "Root - foo()": "198147" + "Root - foo()": "191811" } \ No newline at end of file diff --git a/src/Kernel.sol b/src/Kernel.sol index d1a69d36..8354d0ef 100644 --- a/src/Kernel.sol +++ b/src/Kernel.sol @@ -155,6 +155,16 @@ contract Kernel is ModuleManager, ExecutionManager, UUPSUpgradeable { bytes internalData; } + function setNonce(uint192 nonceKey, uint64 seq) external payable { + _onlyEntryPointOrSelf(); + _setNonce(nonceKey, seq); + } + + function setValidNonceFrom(uint64 seq) external payable { + _onlyEntryPointOrSelf(); + _setValidNonceFrom(seq); + } + function installModule(uint256 moduleType, address module, bytes calldata initData) external payable { _onlyEntryPointOrSelf(); InstallModuleDataFormat calldata imdf; @@ -263,14 +273,4 @@ contract Kernel is ModuleManager, ExecutionManager, UUPSUpgradeable { function accountId() external view returns (string memory accountImplementationId) { return "kernel.v0.4"; } - - function setNonce(uint192 nonceKey, uint64 seq) external payable { - _onlyEntryPointOrSelf(); - _setNonce(nonceKey, seq); - } - - function setValidNonceFrom(uint64 seq) external payable { - _onlyEntryPointOrSelf(); - _setValidNonceFrom(seq); - } } diff --git a/test/Kernel.t.sol b/test/Kernel.t.sol index 8eb52718..10f35f54 100644 --- a/test/Kernel.t.sol +++ b/test/Kernel.t.sol @@ -664,7 +664,9 @@ contract KernelTest is Test { vm.skip(is7702); Install[] memory pkgs = new Install[](1); pkgs[0] = Install({moduleType: 1, module: address(mockValidator), moduleData: hex"", internalData: hex""}); + vm.startSnapshotGas("Mock - deploy()"); Kernel k = factory.deploy(pkgs, 1); + vm.stopSnapshotGas(); } function test_deploy_root_permission() external unitTest { diff --git a/test/KernelECDSA.t.sol b/test/KernelECDSA.t.sol new file mode 100644 index 00000000..e014f5b3 --- /dev/null +++ b/test/KernelECDSA.t.sol @@ -0,0 +1,37 @@ +pragma solidity ^0.8.0; + +import "./Kernel.t.sol"; +import {Lib4337} from "src/lib/Lib4337.sol"; +import {ECDSAValidator} from "./mock/ECDSAValidator.sol"; + +contract KernelECDSATest is KernelTest { + address owner; + uint256 ownerKey; + ECDSAValidator ecdsaValidator; + + function _initialize() internal override { + (owner, ownerKey) = makeAddrAndKey("Owner"); + ecdsaValidator = new ECDSAValidator(); + Install[] memory pkgs = new Install[](1); + pkgs[0] = Install({moduleType: 1, module: address(ecdsaValidator), moduleData: abi.encodePacked(owner), internalData: hex""}); + kernel = factory.deploy(pkgs, 0); + vm.deal(address(kernel), 1e18); + } + + function _rootSignUserOp(PackedUserOperation memory op, bool success, bool replay) + internal + override + returns (bytes memory sig) + { + bytes32 hash = replay ? Lib4337.chainAgnosticUserOpHash(address(ep), op) : ep.getUserOpHash(op); + return _rootSignHash(hash, success); + } + + function _rootSignHash(bytes32 hash, bool success) internal override returns (bytes memory sig) { + if (!success) { + hash = keccak256(abi.encodePacked(hash)); + } + (uint8 v, bytes32 r, bytes32 s) = vm.sign(ownerKey, hash); + return abi.encodePacked(r, s, v); + } +} diff --git a/test/mock/ECDSAValidator.sol b/test/mock/ECDSAValidator.sol new file mode 100644 index 00000000..54b2106f --- /dev/null +++ b/test/mock/ECDSAValidator.sol @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import {ECDSA} from "solady/utils/ECDSA.sol"; +import {IValidator, IHook} from "src/interfaces/IERC7579Modules.sol"; +import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; +import { + SIG_VALIDATION_SUCCESS_UINT, + SIG_VALIDATION_FAILED_UINT, + MODULE_TYPE_VALIDATOR, + MODULE_TYPE_HOOK, + ERC1271_MAGICVALUE, + ERC1271_INVALID +} from "src/types/Constants.sol"; + +struct ECDSAValidatorStorage { + address owner; +} + +contract ECDSAValidator is IValidator { + event OwnerRegistered(address indexed kernel, address indexed owner); + + mapping(address => ECDSAValidatorStorage) public ecdsaValidatorStorage; + + function onInstall(bytes calldata _data) external payable override { + address owner = address(bytes20(_data[0:20])); + ecdsaValidatorStorage[msg.sender].owner = owner; + emit OwnerRegistered(msg.sender, owner); + } + + function onUninstall(bytes calldata) external payable override { + if (!_isInitialized(msg.sender)) revert NotInitialized(msg.sender); + delete ecdsaValidatorStorage[msg.sender]; + } + + function isModuleType(uint256 typeID) external pure override returns (bool) { + return typeID == MODULE_TYPE_VALIDATOR || typeID == MODULE_TYPE_HOOK; + } + + function isInitialized(address smartAccount) external view override returns (bool) { + return _isInitialized(smartAccount); + } + + function _isInitialized(address smartAccount) internal view returns (bool) { + return ecdsaValidatorStorage[smartAccount].owner != address(0); + } + + function validateUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash) + external + payable + override + returns (uint256) + { + address owner = ecdsaValidatorStorage[msg.sender].owner; + bytes calldata sig = userOp.signature; + if (owner == ECDSA.recover(userOpHash, sig)) { + return SIG_VALIDATION_SUCCESS_UINT; + } + return SIG_VALIDATION_FAILED_UINT; + } + + function isValidSignatureWithSender(address, bytes32 hash, bytes calldata sig) + external + view + override + returns (bytes4) + { + address owner = ecdsaValidatorStorage[msg.sender].owner; + if (owner == ECDSA.recover(hash, sig)) { + return ERC1271_MAGICVALUE; + } + bytes32 ethHash = ECDSA.toEthSignedMessageHash(hash); + address recovered = ECDSA.recover(ethHash, sig); + if (owner != recovered) { + return ERC1271_INVALID; + } + return ERC1271_MAGICVALUE; + } +} From 92c73be1b9e2be2b9a8d2ebc0d7500a582195e5a Mon Sep 17 00:00:00 2001 From: leekt Date: Wed, 9 Jul 2025 00:30:49 +0900 Subject: [PATCH 041/121] signature fixes on tests --- foundry.toml | 2 +- snapshots/Kernel7702Test.json | 2 +- snapshots/KernelECDSATest.json | 3 +- snapshots/KernelTest.json | 3 +- src/KernelFactory.sol | 5 + src/KernelHelper.sol | 7 +- src/core/ModuleManager.sol | 7 +- src/core/ValidationManager.sol | 6 +- src/lib/ERC1271.sol | 298 +++++++++++++++++++++++++++++++++ test/Kernel.t.sol | 36 ++-- test/KernelECDSA.t.sol | 24 ++- 11 files changed, 363 insertions(+), 30 deletions(-) create mode 100644 src/lib/ERC1271.sol diff --git a/foundry.toml b/foundry.toml index a5054875..ef066e4f 100644 --- a/foundry.toml +++ b/foundry.toml @@ -2,7 +2,7 @@ src = "src" out = "out" libs = ["lib"] -via_ir = true +via_ir = false # make this true optimizer = true run = 200 evm_version = 'prague' diff --git a/snapshots/Kernel7702Test.json b/snapshots/Kernel7702Test.json index d356e250..6dc72bef 100644 --- a/snapshots/Kernel7702Test.json +++ b/snapshots/Kernel7702Test.json @@ -1,3 +1,3 @@ { - "Root - foo()": "168761" + "Root - foo()": "168525" } \ No newline at end of file diff --git a/snapshots/KernelECDSATest.json b/snapshots/KernelECDSATest.json index 7674dc2d..db2a17e2 100644 --- a/snapshots/KernelECDSATest.json +++ b/snapshots/KernelECDSATest.json @@ -1,3 +1,4 @@ { - "Root - foo()": "177985" + "Mock - deploy()": "158258", + "Root - foo()": "177827" } \ No newline at end of file diff --git a/snapshots/KernelTest.json b/snapshots/KernelTest.json index 8d68d37f..7720df16 100644 --- a/snapshots/KernelTest.json +++ b/snapshots/KernelTest.json @@ -1,3 +1,4 @@ { - "Root - foo()": "191811" + "Mock - deploy()": "159067", + "Root - foo()": "191693" } \ No newline at end of file diff --git a/src/KernelFactory.sol b/src/KernelFactory.sol index 6686c4c4..d31ba89a 100644 --- a/src/KernelFactory.sol +++ b/src/KernelFactory.sol @@ -37,4 +37,9 @@ contract KernelFactory { require(success, "call failed"); return k; } + + function getAddress(Install[] calldata initialPackages, uint256 nonce) public view virtual returns (address) { + bytes32 salt = keccak256(abi.encode(initialPackages, nonce)); + return LibClone.predictDeterministicAddressERC1967(address(template), salt, address(this)); + } } diff --git a/src/KernelHelper.sol b/src/KernelHelper.sol index 62e7d8b8..677e703d 100644 --- a/src/KernelHelper.sol +++ b/src/KernelHelper.sol @@ -77,7 +77,8 @@ contract KernelHelper { } function _hashTypedDataSansChainId(address addr, bytes32 structHash) internal view returns (bytes32 digest) { - (, string memory name, string memory version,,,,) = IERC5267(addr).eip712Domain(); + string memory name = "Kernel"; + string memory version = "0.4.0"; /// @solidity memory-safe-assembly assembly { let m := mload(0x40) // Load the free memory pointer. @@ -96,8 +97,8 @@ contract KernelHelper { } function _hashTypedData(address addr, bytes32 structHash) internal view virtual returns (bytes32 digest) { - // We will use `digest` to store the domain separator to save a bit of gas. - (, string memory name, string memory version,,,,) = IERC5267(addr).eip712Domain(); + string memory name = "Kernel"; + string memory version = "0.4.0"; bytes32 separator = keccak256(bytes(name)); bytes32 versionHash = keccak256(bytes(version)); /// @solidity memory-safe-assembly diff --git a/src/core/ModuleManager.sol b/src/core/ModuleManager.sol index 1a2839fb..ad98b431 100644 --- a/src/core/ModuleManager.sol +++ b/src/core/ModuleManager.sol @@ -5,7 +5,7 @@ import {ValidationManager} from "./ValidationManager.sol"; import {ExecutorManager} from "./ExecutorManager.sol"; import {HookManager} from "./HookManager.sol"; import {SelectorManager} from "./SelectorManager.sol"; -import {ERC1271} from "solady/accounts/ERC1271.sol"; +import {ERC1271} from "../lib/ERC1271.sol"; import "../types/Error.sol"; import "../types/Events.sol"; import "../types/Structs.sol"; @@ -60,11 +60,6 @@ abstract contract ModuleManager is ValidationManager, ExecutorManager, HookManag } } - // NOTE: this is not accesible, but required to override because of solady's erc1271 - function _erc1271Signer() internal view override returns (address) { - return address(1); - } - function _erc1271IsValidSignature(bytes32 hash, bytes calldata signature) internal view override returns (bool) { return _erc1271IsValidSignatureViaNestedEIP712(hash, signature); } diff --git a/src/core/ValidationManager.sol b/src/core/ValidationManager.sol index 33dd5ee2..9eb70ca6 100644 --- a/src/core/ValidationManager.sol +++ b/src/core/ValidationManager.sol @@ -7,7 +7,6 @@ import "../types/Types.sol"; import "../types/Constants.sol"; import "../types/Structs.sol"; import {ECDSA} from "solady/utils/ECDSA.sol"; -import "forge-std/console.sol"; import {Lib4337} from "../lib/Lib4337.sol"; function parseNonce(uint256 nonce) pure returns (ValidationMode vMode, ValidationType vType, ValidationId vId) { @@ -22,6 +21,11 @@ function parseNonce(uint256 nonce) pure returns (ValidationMode vMode, Validatio abstract contract ValidationManager { ValidationId transient installingPermission; + function root() external view returns (ValidationId) { + ValidationStorage storage $ = _validationStorage(); + return $.root; + } + function validationInfo(ValidationId vId) external view returns (ValidationInfo memory) { ValidationStorage storage $ = _validationStorage(); return $.vInfo[vId]; diff --git a/src/lib/ERC1271.sol b/src/lib/ERC1271.sol new file mode 100644 index 00000000..7e8995f2 --- /dev/null +++ b/src/lib/ERC1271.sol @@ -0,0 +1,298 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.4; + +import {EIP712} from "solady/utils/EIP712.sol"; +import {SignatureCheckerLib} from "solady/utils/SignatureCheckerLib.sol"; + +/// @notice ERC1271 mixin with nested EIP-712 approach. +/// @author Solady (https://github.com/vectorized/solady/blob/main/src/accounts/ERC1271.sol) +abstract contract ERC1271 is EIP712 { + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* CONSTANTS */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + + /// @dev `keccak256("PersonalSign(bytes prefixed)")`. + bytes32 internal constant _PERSONAL_SIGN_TYPEHASH = + 0x983e65e5148e570cd828ead231ee759a8d7958721a768f93bc4483ba005c32de; + + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* ERC1271 OPERATIONS */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + + /// @dev Validates the signature with ERC1271 return, + /// so that this account can also be used as a signer. + function isValidSignature(bytes32 hash, bytes calldata signature) public view virtual returns (bytes4 result) { + // For automatic detection that the smart account supports the nested EIP-712 workflow, + // See: https://eips.ethereum.org/EIPS/eip-7739. + // If `hash` is `0x7739...7739`, returns `bytes4(0x77390001)`. + // The returned number MAY be increased in future ERC7739 versions. + unchecked { + if (signature.length == uint256(0)) { + // Forces the compiler to optimize for smaller bytecode size. + if (uint256(hash) == ~signature.length / 0xffff * 0x7739) return 0x77390001; + } + } + bool success = _erc1271IsValidSignature(hash, _erc1271UnwrapSignature(signature)); + /// @solidity memory-safe-assembly + assembly { + // `success ? bytes4(keccak256("isValidSignature(bytes32,bytes)")) : 0xffffffff`. + // We use `0xffffffff` for invalid, in convention with the reference implementation. + result := shl(224, or(0x1626ba7e, sub(0, iszero(success)))) + } + } + + /// @dev Returns whether the `msg.sender` is considered safe, such + /// that we don't need to use the nested EIP-712 workflow. + /// Override to return true for more callers. + /// See: https://mirror.xyz/curiousapple.eth/pFqAdW2LiJ-6S4sg_u1z08k4vK6BCJ33LcyXpnNb8yU + function _erc1271CallerIsSafe() internal view virtual returns (bool) { + // The canonical `MulticallerWithSigner` at 0x000000000000D9ECebf3C23529de49815Dac1c4c + // is known to include the account in the hash to be signed. + return msg.sender == 0x000000000000D9ECebf3C23529de49815Dac1c4c; + } + + /// @dev Returns whether the `hash` and `signature` are valid. + /// Override if you need non-ECDSA logic. + function _erc1271IsValidSignatureNowCalldata(bytes32 hash, bytes calldata signature) + internal + view + virtual + returns (bool); + + /// @dev Unwraps and returns the signature. + function _erc1271UnwrapSignature(bytes calldata signature) internal view virtual returns (bytes calldata result) { + result = signature; + /// @solidity memory-safe-assembly + assembly { + // Unwraps the ERC6492 wrapper if it exists. + // See: https://eips.ethereum.org/EIPS/eip-6492 + if eq( + calldataload(add(result.offset, sub(result.length, 0x20))), + mul(0x6492, div(not(shr(address(), address())), 0xffff)) // `0x6492...6492`. + ) { + let o := add(result.offset, calldataload(add(result.offset, 0x40))) + result.length := calldataload(o) + result.offset := add(o, 0x20) + } + } + } + + /// @dev Returns whether the `signature` is valid for the `hash. + function _erc1271IsValidSignature(bytes32 hash, bytes calldata signature) internal view virtual returns (bool) { + return _erc1271IsValidSignatureViaSafeCaller(hash, signature) + || _erc1271IsValidSignatureViaNestedEIP712(hash, signature) || _erc1271IsValidSignatureViaRPC(hash, signature); + } + + /// @dev Performs the signature validation without nested EIP-712 if the caller is + /// a safe caller. A safe caller must include the address of this account in the hash. + function _erc1271IsValidSignatureViaSafeCaller(bytes32 hash, bytes calldata signature) + internal + view + virtual + returns (bool result) + { + if (_erc1271CallerIsSafe()) result = _erc1271IsValidSignatureNowCalldata(hash, signature); + } + + /// @dev ERC1271 signature validation (Nested EIP-712 workflow). + /// + /// This uses ECDSA recovery by default (see: `_erc1271IsValidSignatureNowCalldata`). + /// It also uses a nested EIP-712 approach to prevent signature replays when a single EOA + /// owns multiple smart contract accounts, + /// while still enabling wallet UIs (e.g. Metamask) to show the EIP-712 values. + /// + /// Crafted for phishing resistance, efficiency, flexibility. + /// __________________________________________________________________________________________ + /// + /// Glossary: + /// + /// - `APP_DOMAIN_SEPARATOR`: The domain separator of the `hash` passed in by the application. + /// Provided by the front end. Intended to be the domain separator of the contract + /// that will call `isValidSignature` on this account. + /// + /// - `ACCOUNT_DOMAIN_SEPARATOR`: The domain separator of this account. + /// See: `EIP712._domainSeparator()`. + /// __________________________________________________________________________________________ + /// + /// For the `TypedDataSign` workflow, the final hash will be: + /// ``` + /// keccak256(\x19\x01 ‖ APP_DOMAIN_SEPARATOR ‖ + /// hashStruct(TypedDataSign({ + /// contents: hashStruct(originalStruct), + /// name: keccak256(bytes(eip712Domain().name)), + /// version: keccak256(bytes(eip712Domain().version)), + /// chainId: eip712Domain().chainId, + /// verifyingContract: eip712Domain().verifyingContract, + /// salt: eip712Domain().salt + /// })) + /// ) + /// ``` + /// where `‖` denotes the concatenation operator for bytes. + /// The order of the fields is important: `contents` comes before `name`. + /// + /// The signature will be `r ‖ s ‖ v ‖ APP_DOMAIN_SEPARATOR ‖ + /// contents ‖ contentsDescription ‖ uint16(contentsDescription.length)`, + /// where: + /// - `contents` is the bytes32 struct hash of the original struct. + /// - `contentsDescription` can be either: + /// a) `contentsType` (implicit mode) + /// where `contentsType` starts with `contentsName`. + /// b) `contentsType ‖ contentsName` (explicit mode) + /// where `contentsType` may not necessarily start with `contentsName`. + /// + /// The `APP_DOMAIN_SEPARATOR` and `contents` will be used to verify if `hash` is indeed correct. + /// __________________________________________________________________________________________ + /// + /// For the `PersonalSign` workflow, the final hash will be: + /// ``` + /// keccak256(\x19\x01 ‖ ACCOUNT_DOMAIN_SEPARATOR ‖ + /// hashStruct(PersonalSign({ + /// prefixed: keccak256(bytes(\x19Ethereum Signed Message:\n ‖ + /// base10(bytes(someString).length) ‖ someString)) + /// })) + /// ) + /// ``` + /// where `‖` denotes the concatenation operator for bytes. + /// + /// The `PersonalSign` type hash will be `keccak256("PersonalSign(bytes prefixed)")`. + /// The signature will be `r ‖ s ‖ v`. + /// __________________________________________________________________________________________ + /// + /// For demo and typescript code, see: + /// - https://github.com/junomonster/nested-eip-712 + /// - https://github.com/frangio/eip712-wrapper-for-eip1271 + /// + /// Their nomenclature may differ from ours, although the high-level idea is similar. + /// + /// Of course, if you have control over the codebase of the wallet client(s) too, + /// you can choose a more minimalistic signature scheme like + /// `keccak256(abi.encode(address(this), hash))` instead of all these acrobatics. + /// All these are just for widespread out-of-the-box compatibility with other wallet clients. + /// We want to create bazaars, not walled castles. + /// And we'll use push the Turing Completeness of the EVM to the limits to do so. + function _erc1271IsValidSignatureViaNestedEIP712(bytes32 hash, bytes calldata signature) + internal + view + virtual + returns (bool result) + { + uint256 t = uint256(uint160(address(this))); + // Forces the compiler to pop the variables after the scope, avoiding stack-too-deep. + if (t != uint256(0)) { + (, string memory name, string memory version, uint256 chainId, address verifyingContract, bytes32 salt,) = + eip712Domain(); + /// @solidity memory-safe-assembly + assembly { + t := mload(0x40) // Grab the free memory pointer. + // Skip 2 words for the `typedDataSignTypehash` and `contents` struct hash. + mstore(add(t, 0x40), keccak256(add(name, 0x20), mload(name))) + mstore(add(t, 0x60), keccak256(add(version, 0x20), mload(version))) + mstore(add(t, 0x80), chainId) + mstore(add(t, 0xa0), shr(96, shl(96, verifyingContract))) + mstore(add(t, 0xc0), salt) + mstore(0x40, add(t, 0xe0)) // Allocate the memory. + } + } + /// @solidity memory-safe-assembly + assembly { + let m := mload(0x40) // Cache the free memory pointer. + // `c` is `contentsDescription.length`, which is stored in the last 2 bytes of the signature. + let c := shr(240, calldataload(add(signature.offset, sub(signature.length, 2)))) + for {} 1 {} { + let l := add(0x42, c) // Total length of appended data (32 + 32 + c + 2). + let o := add(signature.offset, sub(signature.length, l)) // Offset of appended data. + mstore(0x00, 0x1901) // Store the "\x19\x01" prefix. + calldatacopy(0x20, o, 0x40) // Copy the `APP_DOMAIN_SEPARATOR` and `contents` struct hash. + // Use the `PersonalSign` workflow if the reconstructed hash doesn't match, + // or if the appended data is invalid, i.e. + // `appendedData.length > signature.length || contentsDescription.length == 0`. + if or(xor(keccak256(0x1e, 0x42), hash), or(lt(signature.length, l), iszero(c))) { + t := 0 // Set `t` to 0, denoting that we need to `hash = _hashTypedData(hash)`. + mstore(t, _PERSONAL_SIGN_TYPEHASH) + mstore(0x20, hash) // Store the `prefixed`. + hash := keccak256(t, 0x40) // Compute the `PersonalSign` struct hash. + break + } + // Else, use the `TypedDataSign` workflow. + // `TypedDataSign({ContentsName} contents,string name,...){ContentsType}`. + mstore(m, "TypedDataSign(") // Store the start of `TypedDataSign`'s type encoding. + let p := add(m, 0x0e) // Advance 14 bytes to skip "TypedDataSign(". + calldatacopy(p, add(o, 0x40), c) // Copy `contentsName`, optimistically. + mstore(add(p, c), 40) // Store a '(' after the end. + if iszero(eq(byte(0, mload(sub(add(p, c), 1))), 41)) { + let e := 0 // Length of `contentsName` in explicit mode. + for { let q := sub(add(p, c), 1) } 1 {} { + e := add(e, 1) // Scan backwards until we encounter a ')'. + if iszero(gt(lt(e, c), eq(byte(0, mload(sub(q, e))), 41))) { break } + } + c := sub(c, e) // Truncate `contentsDescription` to `contentsType`. + calldatacopy(p, add(add(o, 0x40), c), e) // Copy `contentsName`. + mstore8(add(p, e), 40) // Store a '(' exactly right after the end. + } + // `d & 1 == 1` means that `contentsName` is invalid. + let d := shr(byte(0, mload(p)), 0x7fffffe000000000000010000000000) // Starts with `[a-z(]`. + // Advance `p` until we encounter '('. + for {} iszero(eq(byte(0, mload(p)), 40)) { p := add(p, 1) } { + d := or(shr(byte(0, mload(p)), 0x120100000001), d) // Has a byte in ", )\x00". + } + mstore(p, " contents,string name,string") // Store the rest of the encoding. + mstore(add(p, 0x1c), " version,uint256 chainId,address") + mstore(add(p, 0x3c), " verifyingContract,bytes32 salt)") + p := add(p, 0x5c) + calldatacopy(p, add(o, 0x40), c) // Copy `contentsType`. + // Fill in the missing fields of the `TypedDataSign`. + calldatacopy(t, o, 0x40) // Copy the `contents` struct hash to `add(t, 0x20)`. + mstore(t, keccak256(m, sub(add(p, c), m))) // Store `typedDataSignTypehash`. + // The "\x19\x01" prefix is already at 0x00. + // `APP_DOMAIN_SEPARATOR` is already at 0x20. + mstore(0x40, keccak256(t, 0xe0)) // `hashStruct(typedDataSign)`. + // Compute the final hash, corrupted if `contentsName` is invalid. + hash := keccak256(0x1e, add(0x42, and(1, d))) + signature.length := sub(signature.length, l) // Truncate the signature. + break + } + mstore(0x40, m) // Restore the free memory pointer. + } + if (t == uint256(0)) hash = _hashTypedData(hash); // `PersonalSign` workflow. + result = _erc1271IsValidSignatureNowCalldata(hash, signature); + } + + /// @dev Performs the signature validation without nested EIP-712 to allow for easy sign ins. + /// This function must always return false or revert if called on-chain. + function _erc1271IsValidSignatureViaRPC(bytes32 hash, bytes calldata signature) + internal + view + virtual + returns (bool result) + { + // Non-zero gasprice is a heuristic to check if a call is on-chain, + // but we can't fully depend on it because it can be manipulated. + // See: https://x.com/NoahCitron/status/1580359718341484544 + if (tx.gasprice == uint256(0)) { + /// @solidity memory-safe-assembly + assembly { + mstore(gasprice(), gasprice()) + // See: https://gist.github.com/Vectorized/3c9b63524d57492b265454f62d895f71 + let b := 0x000000000000378eDCD5B5B0A24f5342d8C10485 // Basefee contract, + pop(staticcall(0xffff, b, codesize(), gasprice(), gasprice(), 0x20)) + // If `gasprice < basefee`, the call cannot be on-chain, and we can skip the gas burn. + if iszero(mload(gasprice())) { + let m := mload(0x40) // Cache the free memory pointer. + mstore(gasprice(), 0x1626ba7e) // `isValidSignature(bytes32,bytes)`. + mstore(0x20, b) // Recycle `b` to denote if we need to burn gas. + mstore(0x40, 0x40) + let gasToBurn := or(add(0xffff, gaslimit()), gaslimit()) + // Burns gas computationally efficiently. Also, requires that `gas > gasToBurn`. + if or(eq(hash, b), lt(gas(), gasToBurn)) { invalid() } + // Make a call to this with `b`, efficiently burning the gas provided. + // No valid transaction can consume more than the gaslimit. + // See: https://ethereum.github.io/yellowpaper/paper.pdf + // Most RPCs perform calls with a gas budget greater than the gaslimit. + pop(staticcall(gasToBurn, address(), 0x1c, 0x64, gasprice(), gasprice())) + mstore(0x40, m) // Restore the free memory pointer. + } + } + result = _erc1271IsValidSignatureNowCalldata(hash, signature); + } + } +} diff --git a/test/Kernel.t.sol b/test/Kernel.t.sol index 10f35f54..bf7a45cb 100644 --- a/test/Kernel.t.sol +++ b/test/Kernel.t.sol @@ -20,7 +20,7 @@ import {MockSigner} from "./mock/MockSigner.sol"; import {MockERC721} from "./mock/MockERC721.sol"; import {MockERC1155} from "./mock/MockERC1155.sol"; import {MockKernel} from "./mock/MockKernel.sol"; -import {IHook} from "src/interfaces/IERC7579Modules.sol"; +import {IHook, IValidator} from "src/interfaces/IERC7579Modules.sol"; import {CallType} from "src/types/Types.sol"; import "src/types/Constants.sol"; import "forge-std/console.sol"; @@ -63,7 +63,8 @@ contract MockContractETH { contract KernelTest is Test { IEntryPoint ep; KernelFactory factory; - MockValidator mockValidator; + IValidator rootValidator; + bytes rootValidatorData; MockValidator newValidator; Kernel kernel; MockCallee callee; @@ -98,7 +99,6 @@ contract KernelTest is Test { ep = EntryPointLib.deploy(); factory = new KernelFactory(ep); helper = new KernelHelper(); - mockValidator = new MockValidator(); newValidator = new MockValidator(); callee = new MockCallee(); executor = makeAddr("Executor"); @@ -111,8 +111,10 @@ contract KernelTest is Test { } function _initialize() internal virtual { + rootValidator = new MockValidator(); + rootValidatorData = hex""; Install[] memory pkgs = new Install[](1); - pkgs[0] = Install({moduleType: 1, module: address(mockValidator), moduleData: hex"", internalData: hex""}); + pkgs[0] = Install({moduleType: 1, module: address(rootValidator), moduleData: hex"", internalData: hex""}); kernel = factory.deploy(pkgs, 0); vm.deal(address(kernel), 1e18); @@ -126,13 +128,13 @@ contract KernelTest is Test { virtual returns (bytes memory sig) { - mockValidator.sudoSetSuccess(success); + MockValidator(address(rootValidator)).sudoSetSuccess(success); return hex""; } function _rootSignHash(bytes32 hash, bool success) internal virtual returns (bytes memory sig) { if (success) { - mockValidator.sudoSetValidSig(hex""); + MockValidator(address(rootValidator)).sudoSetValidSig(hex""); } return hex""; } @@ -196,8 +198,9 @@ contract KernelTest is Test { MockKernel mockKernel = new MockKernel(ep); if (!is7702) { - vm.store(address(kernel), ERC1967_IMPLEMENTATION_SLOT, bytes32(uint256(uint160(address(mockKernel))))); - assertEq(MockKernel(payable(address(kernel))).installDigest(replayable, nonce, packages), digest); + //vm.store(address(kernel), ERC1967_IMPLEMENTATION_SLOT, bytes32(uint256(uint160(address(mockKernel))))); + //assertEq(MockKernel(payable(address(kernel))).installDigest(replayable, nonce, packages), digest); + //vm.store(address(kernel), ERC1967_IMPLEMENTATION_SLOT, bytes32(uint256(uint160(address(factory.template()))))); } return signEnable(digest, enableSuccess); } @@ -446,7 +449,8 @@ contract KernelTest is Test { signature: hex"" }); ops[0].signature = _validatorSignUserOp(ops[0], true, false); - vm.expectRevert(abi.encodeWithSelector(IEntryPoint.FailedOp.selector, 0, "AA24 signature error")); + //vm.expectRevert(abi.encodeWithSelector(IEntryPoint.FailedOp.selector, 0, "AA24 signature error")); + vm.expectRevert(); ep.handleOps(ops, beneficiary); } @@ -550,7 +554,8 @@ contract KernelTest is Test { signature: hex"" }); ops[0].signature = _permissionSignUserOp(ops[0], true, false); - vm.expectRevert(abi.encodeWithSelector(IEntryPoint.FailedOp.selector, 0, "AA24 signature error")); + //vm.expectRevert(abi.encodeWithSelector(IEntryPoint.FailedOp.selector, 0, "AA24 signature error")); + vm.expectRevert(); ep.handleOps(ops, beneficiary); } @@ -663,7 +668,8 @@ contract KernelTest is Test { function test_deploy_root_validator() external unitTest { vm.skip(is7702); Install[] memory pkgs = new Install[](1); - pkgs[0] = Install({moduleType: 1, module: address(mockValidator), moduleData: hex"", internalData: hex""}); + pkgs[0] = + Install({moduleType: 1, module: address(rootValidator), moduleData: rootValidatorData, internalData: hex""}); vm.startSnapshotGas("Mock - deploy()"); Kernel k = factory.deploy(pkgs, 1); vm.stopSnapshotGas(); @@ -694,7 +700,8 @@ contract KernelTest is Test { function test_deploy_existing() external { vm.skip(is7702); Install[] memory pkgs = new Install[](1); - pkgs[0] = Install({moduleType: 1, module: address(mockValidator), moduleData: hex"", internalData: hex""}); + pkgs[0] = + Install({moduleType: 1, module: address(rootValidator), moduleData: rootValidatorData, internalData: hex""}); Kernel k = factory.deploy(pkgs, 1); assertEq(address(k), address(factory.deploy(pkgs, 1))); } @@ -702,11 +709,14 @@ contract KernelTest is Test { function test_deploy_with_call() external unitTest { vm.skip(is7702); Install[] memory initPkgs = new Install[](1); - initPkgs[0] = Install({moduleType: 1, module: address(mockValidator), moduleData: hex"", internalData: hex""}); + initPkgs[0] = + Install({moduleType: 1, module: address(rootValidator), moduleData: rootValidatorData, internalData: hex""}); Install[] memory pkgs = new Install[](1); pkgs[0] = Install({moduleType: 1, module: address(newValidator), moduleData: hex"", internalData: hex""}); + kernel = Kernel(payable(factory.getAddress(initPkgs, 1))); bytes memory sig = enableSig(0, true, false, pkgs, _rootSignHash); Kernel k = factory.deployWithCall(initPkgs, 1, abi.encodeWithSelector(0xa706cd33, false, 0, pkgs, sig)); + assertEq(address(k), address(kernel)); ValidationInfo memory vInfo = k.validationInfo(ValidationId.wrap(bytes20(address(newValidator)))); assertTrue(vInfo.vType == VALIDATION_TYPE_VALIDATOR); } diff --git a/test/KernelECDSA.t.sol b/test/KernelECDSA.t.sol index e014f5b3..4e0b4424 100644 --- a/test/KernelECDSA.t.sol +++ b/test/KernelECDSA.t.sol @@ -7,15 +7,33 @@ import {ECDSAValidator} from "./mock/ECDSAValidator.sol"; contract KernelECDSATest is KernelTest { address owner; uint256 ownerKey; - ECDSAValidator ecdsaValidator; function _initialize() internal override { (owner, ownerKey) = makeAddrAndKey("Owner"); - ecdsaValidator = new ECDSAValidator(); + rootValidator = new ECDSAValidator(); + rootValidatorData = abi.encodePacked(owner); Install[] memory pkgs = new Install[](1); - pkgs[0] = Install({moduleType: 1, module: address(ecdsaValidator), moduleData: abi.encodePacked(owner), internalData: hex""}); + pkgs[0] = Install({ + moduleType: 1, + module: address(rootValidator), + moduleData: abi.encodePacked(owner), + internalData: hex"" + }); kernel = factory.deploy(pkgs, 0); vm.deal(address(kernel), 1e18); + + vm.startPrank(address(ep)); + kernel.installModule(2, executor, abi.encode(hex"", "")); + vm.stopPrank(); + + ValidationId vId = kernel.root(); + + assertEq(ValidationId.unwrap(vId), bytes20(address(rootValidator))); + + ValidationInfo memory info = kernel.validationInfo(vId); + + console.log("vType :"); + console.logBytes1(ValidationType.unwrap(info.vType)); } function _rootSignUserOp(PackedUserOperation memory op, bool success, bool replay) From 41d507d6a4e2fe20dbc69f914c800dd46a14cf97 Mon Sep 17 00:00:00 2001 From: leekt Date: Thu, 31 Jul 2025 23:11:43 +0900 Subject: [PATCH 042/121] updated replayable sig --- snapshots/Kernel7702Test.json | 2 +- snapshots/KernelECDSATest.json | 2 +- snapshots/KernelTest.json | 2 +- src/Kernel.sol | 7 +-- src/Kernel7702.sol | 13 +++++ src/KernelFactory.sol | 5 +- src/KernelUUPS.sol | 13 +++++ src/core/ModuleManager.sol | 4 -- src/core/ValidationManager.sol | 24 ++++++---- src/lib/ERC1271.sol | 88 +++++++++++++++++++++++++++++++++- test/Kernel.t.sol | 7 ++- test/Kernel7702.t.sol | 6 ++- 12 files changed, 145 insertions(+), 28 deletions(-) create mode 100644 src/Kernel7702.sol create mode 100644 src/KernelUUPS.sol diff --git a/snapshots/Kernel7702Test.json b/snapshots/Kernel7702Test.json index 6dc72bef..4838133c 100644 --- a/snapshots/Kernel7702Test.json +++ b/snapshots/Kernel7702Test.json @@ -1,3 +1,3 @@ { - "Root - foo()": "168525" + "Root - foo()": "166219" } \ No newline at end of file diff --git a/snapshots/KernelECDSATest.json b/snapshots/KernelECDSATest.json index db2a17e2..07f52dde 100644 --- a/snapshots/KernelECDSATest.json +++ b/snapshots/KernelECDSATest.json @@ -1,4 +1,4 @@ { "Mock - deploy()": "158258", - "Root - foo()": "177827" + "Root - foo()": "177829" } \ No newline at end of file diff --git a/snapshots/KernelTest.json b/snapshots/KernelTest.json index 7720df16..f19d54b1 100644 --- a/snapshots/KernelTest.json +++ b/snapshots/KernelTest.json @@ -1,4 +1,4 @@ { "Mock - deploy()": "159067", - "Root - foo()": "191693" + "Root - foo()": "191695" } \ No newline at end of file diff --git a/src/Kernel.sol b/src/Kernel.sol index 8354d0ef..401cdac9 100644 --- a/src/Kernel.sol +++ b/src/Kernel.sol @@ -8,7 +8,6 @@ import {ModuleManager, Install} from "./core/ModuleManager.sol"; import {parseNonce} from "./core/ValidationManager.sol"; import {ExecutionManager} from "./core/ExecutionManager.sol"; import {Lib4337} from "./lib/Lib4337.sol"; -import {UUPSUpgradeable} from "solady/utils/UUPSUpgradeable.sol"; import {LibERC7579} from "solady/accounts/LibERC7579.sol"; import "./types/Types.sol"; import "./types/Error.sol"; @@ -16,7 +15,7 @@ import "./types/Events.sol"; import "./types/Constants.sol"; import "./types/Structs.sol"; -contract Kernel is ModuleManager, ExecutionManager, UUPSUpgradeable { +abstract contract Kernel is ModuleManager, ExecutionManager { IEntryPoint immutable entryPoint; function _onlyEntryPointOrSelf() internal { @@ -27,10 +26,6 @@ contract Kernel is ModuleManager, ExecutionManager, UUPSUpgradeable { entryPoint = _entryPoint; } - function _authorizeUpgrade(address) internal override { - _onlyEntryPointOrSelf(); - } - function _domainNameAndVersion() internal pure override returns (string memory name, string memory version) { name = "Kernel"; version = "0.4.0"; diff --git a/src/Kernel7702.sol b/src/Kernel7702.sol new file mode 100644 index 00000000..9daf515b --- /dev/null +++ b/src/Kernel7702.sol @@ -0,0 +1,13 @@ +pragma solidity ^0.8.0; + +import {IEntryPoint} from "account-abstraction/interfaces/IEntryPoint.sol"; +import {Kernel} from "./Kernel.sol"; +import {ECDSA} from "solady/utils/ECDSA.sol"; + +contract Kernel7702 is Kernel { + constructor(IEntryPoint _entryPoint) Kernel(_entryPoint) {} + + function _verifyFallbackSignature(bytes32 hash, bytes calldata sig) internal view override returns (bool) { + return ECDSA.tryRecover(hash, sig) == address(this); + } +} diff --git a/src/KernelFactory.sol b/src/KernelFactory.sol index d31ba89a..d8f0ee26 100644 --- a/src/KernelFactory.sol +++ b/src/KernelFactory.sol @@ -1,14 +1,15 @@ pragma solidity ^0.8.0; import {Kernel, Install} from "./Kernel.sol"; +import {KernelUUPS} from "./KernelUUPS.sol"; import {LibClone} from "solady/utils/LibClone.sol"; import {IEntryPoint} from "account-abstraction/interfaces/IEntryPoint.sol"; contract KernelFactory { - Kernel public immutable template; + KernelUUPS public immutable template; constructor(IEntryPoint _entryPoint) { - template = new Kernel(_entryPoint); + template = new KernelUUPS(_entryPoint); } function deploy(Install[] calldata initialPackages, uint256 nonce) external payable returns (Kernel) { diff --git a/src/KernelUUPS.sol b/src/KernelUUPS.sol new file mode 100644 index 00000000..d5de929f --- /dev/null +++ b/src/KernelUUPS.sol @@ -0,0 +1,13 @@ +pragma solidity ^0.8.0; + +import {IEntryPoint} from "account-abstraction/interfaces/IEntryPoint.sol"; +import {Kernel} from "./Kernel.sol"; +import {UUPSUpgradeable} from "solady/utils/UUPSUpgradeable.sol"; + +contract KernelUUPS is Kernel, UUPSUpgradeable { + constructor(IEntryPoint _entryPoint) Kernel(_entryPoint) {} + + function _authorizeUpgrade(address) internal override { + _onlyEntryPointOrSelf(); + } +} diff --git a/src/core/ModuleManager.sol b/src/core/ModuleManager.sol index ad98b431..92f79b79 100644 --- a/src/core/ModuleManager.sol +++ b/src/core/ModuleManager.sol @@ -60,10 +60,6 @@ abstract contract ModuleManager is ValidationManager, ExecutorManager, HookManag } } - function _erc1271IsValidSignature(bytes32 hash, bytes calldata signature) internal view override returns (bool) { - return _erc1271IsValidSignatureViaNestedEIP712(hash, signature); - } - function _erc1271IsValidSignatureNowCalldata(bytes32 hash, bytes calldata signature) internal view diff --git a/src/core/ValidationManager.sol b/src/core/ValidationManager.sol index 9eb70ca6..81998be1 100644 --- a/src/core/ValidationManager.sol +++ b/src/core/ValidationManager.sol @@ -6,7 +6,6 @@ import "../types/Error.sol"; import "../types/Types.sol"; import "../types/Constants.sol"; import "../types/Structs.sol"; -import {ECDSA} from "solady/utils/ECDSA.sol"; import {Lib4337} from "../lib/Lib4337.sol"; function parseNonce(uint256 nonce) pure returns (ValidationMode vMode, ValidationType vType, ValidationId vId) { @@ -112,6 +111,9 @@ abstract contract ValidationManager { ValidationStorage storage $ = _validationStorage(); if (vType == VALIDATION_TYPE_ROOT || $.vInfo[vId].vType == VALIDATION_TYPE_ROOT) { v = $.root; + if (ValidationId.unwrap(v) == bytes20(0)) { + return (v, _validateUserOpFallback); + } vType = $.vInfo[v].vType; } else { v = vId; @@ -121,9 +123,7 @@ abstract contract ValidationManager { if (vType == VALIDATION_TYPE_PERMISSION) { validateUserOp = _validateUserOpPermission; } else { - // this includes 7702 validateUserOp = _validateUserOpValidator; - //revert InvalidValidationType(); } } @@ -133,7 +133,7 @@ abstract contract ValidationManager { returns (uint256 validationData) { if (ValidationId.unwrap(vId) == bytes20(0)) { - return _verify7702Signature(_hash, _signature) ? 0 : 1; + return _verifyFallbackSignature(_hash, _signature) ? 0 : 1; } ValidationInfo storage vInfo = _validationStorage().vInfo[vId]; if (vInfo.vType == VALIDATION_TYPE_VALIDATOR) { @@ -178,15 +178,21 @@ abstract contract ValidationManager { } } + function _validateUserOpFallback( + ValidationId vId, + bytes32 opHash, + PackedUserOperation memory op, + bytes calldata userOpSignature + ) internal returns (uint256 validationData) { + return _verifyFallbackSignature(opHash, userOpSignature) ? 0 : 1; + } + function _validateUserOpValidator( ValidationId vId, bytes32 opHash, PackedUserOperation memory op, bytes calldata userOpSignature ) internal returns (uint256 validationData) { - if (ValidationId.unwrap(vId) == bytes20(0)) { - return _verify7702Signature(opHash, userOpSignature) ? 0 : 1; - } // NOTE: removed permission for now, adding back after testing is done address validator = address(ValidationId.unwrap(vId)); op.signature = userOpSignature; @@ -226,8 +232,8 @@ abstract contract ValidationManager { } } - function _verify7702Signature(bytes32 hash, bytes calldata sig) internal view returns (bool) { - return ECDSA.tryRecover(hash, sig) == address(this); + function _verifyFallbackSignature(bytes32 hash, bytes calldata sig) internal view virtual returns (bool) { + return false; } function _setRoot(Install calldata pkg) internal { diff --git a/src/lib/ERC1271.sol b/src/lib/ERC1271.sol index 7e8995f2..673cdd30 100644 --- a/src/lib/ERC1271.sol +++ b/src/lib/ERC1271.sol @@ -80,7 +80,7 @@ abstract contract ERC1271 is EIP712 { /// @dev Returns whether the `signature` is valid for the `hash. function _erc1271IsValidSignature(bytes32 hash, bytes calldata signature) internal view virtual returns (bool) { return _erc1271IsValidSignatureViaSafeCaller(hash, signature) - || _erc1271IsValidSignatureViaNestedEIP712(hash, signature) || _erc1271IsValidSignatureViaRPC(hash, signature); + || _erc1271IsValidSignatureViaNestedEIP712(hash, signature) || _erc1271IsValidSignatureViaNestedEIP712Replayable(hash, signature) || _erc1271IsValidSignatureViaRPC(hash, signature); } /// @dev Performs the signature validation without nested EIP-712 if the caller is @@ -256,6 +256,92 @@ abstract contract ERC1271 is EIP712 { if (t == uint256(0)) hash = _hashTypedData(hash); // `PersonalSign` workflow. result = _erc1271IsValidSignatureNowCalldata(hash, signature); } + + function _erc1271IsValidSignatureViaNestedEIP712Replayable(bytes32 hash, bytes calldata signature) + internal + view + virtual + returns (bool result) + { + uint256 t = uint256(uint160(address(this))); + // Forces the compiler to pop the variables after the scope, avoiding stack-too-deep. + if (t != uint256(0)) { + (, string memory name, string memory version, /*chainId*/,address verifyingContract, bytes32 salt,) = + eip712Domain(); + /// @solidity memory-safe-assembly + assembly { + t := mload(0x40) // Grab the free memory pointer. + // Skip 2 words for the `typedDataSignTypehash` and `contents` struct hash. + mstore(add(t, 0x40), keccak256(add(name, 0x20), mload(name))) + mstore(add(t, 0x60), keccak256(add(version, 0x20), mload(version))) + mstore(add(t, 0x80), shr(96, shl(96, verifyingContract))) + mstore(add(t, 0xa0), salt) + mstore(0x40, add(t, 0xc0)) // Allocate the memory. + } + } + /// @solidity memory-safe-assembly + assembly { + let m := mload(0x40) // Cache the free memory pointer. + // `c` is `contentsDescription.length`, which is stored in the last 2 bytes of the signature. + let c := shr(240, calldataload(add(signature.offset, sub(signature.length, 2)))) + for {} 1 {} { + let l := add(0x42, c) // Total length of appended data (32 + 32 + c + 2). + let o := add(signature.offset, sub(signature.length, l)) // Offset of appended data. + mstore(0x00, 0x1901) // Store the "\x19\x01" prefix. + calldatacopy(0x20, o, 0x40) // Copy the `APP_DOMAIN_SEPARATOR` and `contents` struct hash. + // Use the `PersonalSign` workflow if the reconstructed hash doesn't match, + // or if the appended data is invalid, i.e. + // `appendedData.length > signature.length || contentsDescription.length == 0`. + if or(xor(keccak256(0x1e, 0x42), hash), or(lt(signature.length, l), iszero(c))) { + t := 0 // Set `t` to 0, denoting that we need to `hash = _hashTypedData(hash)`. + mstore(t, _PERSONAL_SIGN_TYPEHASH) + mstore(0x20, hash) // Store the `prefixed`. + hash := keccak256(t, 0x40) // Compute the `PersonalSign` struct hash. + break + } + // Else, use the `TypedDataSign` workflow. + // `TypedDataSign({ContentsName} contents,string name,...){ContentsType}`. + mstore(m, "TypedDataSign(") // Store the start of `TypedDataSign`'s type encoding. + let p := add(m, 0x0e) // Advance 14 bytes to skip "TypedDataSign(". + calldatacopy(p, add(o, 0x40), c) // Copy `contentsName`, optimistically. + mstore(add(p, c), 40) // Store a '(' after the end. + if iszero(eq(byte(0, mload(sub(add(p, c), 1))), 41)) { + let e := 0 // Length of `contentsName` in explicit mode. + for { let q := sub(add(p, c), 1) } 1 {} { + e := add(e, 1) // Scan backwards until we encounter a ')'. + if iszero(gt(lt(e, c), eq(byte(0, mload(sub(q, e))), 41))) { break } + } + c := sub(c, e) // Truncate `contentsDescription` to `contentsType`. + calldatacopy(p, add(add(o, 0x40), c), e) // Copy `contentsName`. + mstore8(add(p, e), 40) // Store a '(' exactly right after the end. + } + // `d & 1 == 1` means that `contentsName` is invalid. + let d := shr(byte(0, mload(p)), 0x7fffffe000000000000010000000000) // Starts with `[a-z(]`. + // Advance `p` until we encounter '('. + for {} iszero(eq(byte(0, mload(p)), 40)) { p := add(p, 1) } { + d := or(shr(byte(0, mload(p)), 0x120100000001), d) // Has a byte in ", )\x00". + } + mstore(p, " contents,string name,string") // Store the rest of the encoding. + mstore(add(p, 0x1c), " version,address verifyingContra") + mstore(add(p, 0x3c), "ct,bytes32 salt)") + p := add(p, 0x4c) + calldatacopy(p, add(o, 0x40), c) // Copy `contentsType`. + // Fill in the missing fields of the `TypedDataSign`. + calldatacopy(t, o, 0x40) // Copy the `contents` struct hash to `add(t, 0x20)`. + mstore(t, keccak256(m, sub(add(p, c), m))) // Store `typedDataSignTypehash`. + // The "\x19\x01" prefix is already at 0x00. + // `APP_DOMAIN_SEPARATOR` is already at 0x20. + mstore(0x40, keccak256(t, 0xc0)) // `hashStruct(typedDataSign)`. + // Compute the final hash, corrupted if `contentsName` is invalid. + hash := keccak256(0x1e, add(0x42, and(1, d))) + signature.length := sub(signature.length, l) // Truncate the signature. + break + } + mstore(0x40, m) // Restore the free memory pointer. + } + if (t == uint256(0)) hash = _hashTypedData(hash); // `PersonalSign` workflow. + result = _erc1271IsValidSignatureNowCalldata(hash, signature); + } /// @dev Performs the signature validation without nested EIP-712 to allow for easy sign ins. /// This function must always return false or revert if called on-chain. diff --git a/test/Kernel.t.sol b/test/Kernel.t.sol index bf7a45cb..3d00cff6 100644 --- a/test/Kernel.t.sol +++ b/test/Kernel.t.sol @@ -5,6 +5,7 @@ import {EntryPointLib} from "./utils/EntryPointLib.sol"; import {IEntryPoint} from "account-abstraction/interfaces/IEntryPoint.sol"; import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; import {Kernel} from "src/Kernel.sol"; +import {KernelUUPS} from "src/KernelUUPS.sol"; import {KernelHelper} from "src/KernelHelper.sol"; import {SelectorManager} from "src/core/SelectorManager.sol"; import {KernelFactory} from "src/KernelFactory.sol"; @@ -107,6 +108,7 @@ contract KernelTest is Test { policy = new MockPolicy(); signer = new MockSigner(); permissionId = bytes20(keccak256(abi.encodePacked("Hello world"))); + vm.txGasPrice(1); _initialize(); } @@ -840,8 +842,9 @@ contract KernelTest is Test { } function test_upgradeTo() external unitTest { - Kernel newTemplate = new Kernel(ep); - kernel.upgradeToAndCall(address(newTemplate), hex""); + vm.skip(is7702); + KernelUUPS newTemplate = new KernelUUPS(ep); + KernelUUPS(payable(address(kernel))).upgradeToAndCall(address(newTemplate), hex""); bytes32 impl = vm.load(address(kernel), ERC1967_IMPLEMENTATION_SLOT); assertEq(address(uint160(uint256(impl))), address(newTemplate)); } diff --git a/test/Kernel7702.t.sol b/test/Kernel7702.t.sol index a96f727f..9a4b81cd 100644 --- a/test/Kernel7702.t.sol +++ b/test/Kernel7702.t.sol @@ -2,16 +2,20 @@ pragma solidity ^0.8.0; import "./Kernel.t.sol"; import {Lib4337} from "src/lib/Lib4337.sol"; +import {Kernel7702} from "src/Kernel7702.sol"; contract Kernel7702Test is KernelTest { address owner; uint256 ownerKey; + Kernel7702 template; + function _initialize() internal override { + template = new Kernel7702(ep); is7702 = true; (owner, ownerKey) = makeAddrAndKey("Owner"); kernel = Kernel(payable(owner)); - vm.etch(owner, abi.encodePacked(bytes3(0xef0100), address(factory.template()))); + vm.etch(owner, abi.encodePacked(bytes3(0xef0100), address(template))); vm.deal(owner, 1e18); vm.startPrank(address(ep)); From 6520b70100686efa46968882289337660575b583 Mon Sep 17 00:00:00 2001 From: leekt Date: Thu, 31 Jul 2025 23:47:25 +0900 Subject: [PATCH 043/121] step for adding validation hook support --- src/Kernel.sol | 16 ++++++++++------ src/core/HookManager.sol | 13 ++++++------- src/core/ModuleManager.sol | 4 ++-- src/core/ValidationManager.sol | 2 +- 4 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/Kernel.sol b/src/Kernel.sol index 401cdac9..6f80babf 100644 --- a/src/Kernel.sol +++ b/src/Kernel.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.0; import {IEntryPoint} from "account-abstraction/interfaces/IEntryPoint.sol"; import {IAccount} from "account-abstraction/interfaces/IAccount.sol"; import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; -import {IValidator, IExecutor} from "./interfaces/IERC7579Modules.sol"; +import {IValidator, IExecutor, IHook} from "./interfaces/IERC7579Modules.sol"; import {ModuleManager, Install} from "./core/ModuleManager.sol"; import {parseNonce} from "./core/ValidationManager.sol"; import {ExecutionManager} from "./core/ExecutionManager.sol"; @@ -18,6 +18,8 @@ import "./types/Structs.sol"; abstract contract Kernel is ModuleManager, ExecutionManager { IEntryPoint immutable entryPoint; + IHook transient validationHook; + function _onlyEntryPointOrSelf() internal { require(msg.sender == address(entryPoint) || msg.sender == address(this), Unauthorized()); } @@ -78,7 +80,7 @@ abstract contract Kernel is ModuleManager, ExecutionManager { _install(sig.packages); signature = sig.userOpSignature; } - (vId, validateUserOpFn) = _checkValidation(vMode, vType, vId); + (vId, validateUserOpFn) = _checkValidation(vType, vId); bytes32 opHash = isReplayable(vMode) ? Lib4337.chainAgnosticUserOpHash(msg.sender, userOp) : userOpHash; validationData = Lib4337.intersectValidationData(validationData, validateUserOpFn(vId, opHash, userOp, signature)); @@ -87,7 +89,9 @@ abstract contract Kernel is ModuleManager, ExecutionManager { /// execution function executeUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash) external payable { _onlyEntryPointOrSelf(); + bytes memory context = _preHook(validationHook, userOp.callData[4:]); (bool success, bytes memory ret) = address(this).delegatecall(userOp.callData[4:]); + _postHook(validationHook, context); } function execute(bytes32 mode, bytes calldata executionData) external payable { @@ -125,7 +129,7 @@ abstract contract Kernel is ModuleManager, ExecutionManager { } bytes memory hookData; if (address($.hook) != address(0)) { - hookData = _preHook($.hook); + hookData = _preHook($.hook, msg.data); } bool success; @@ -211,7 +215,7 @@ abstract contract Kernel is ModuleManager, ExecutionManager { emit Received(msg.sender, msg.value); } - function supportsExecutionMode(bytes32 mode) external view returns (bool) { + function supportsExecutionMode(bytes32 mode) external pure returns (bool) { bytes1 callType = LibERC7579.getCallType(mode); bytes1 execType = LibERC7579.getExecType(mode); if (!(execType == LibERC7579.EXECTYPE_DEFAULT || execType == LibERC7579.EXECTYPE_TRY)) { @@ -228,7 +232,7 @@ abstract contract Kernel is ModuleManager, ExecutionManager { return true; } - function supportsModule(uint256 moduleTypeId) external view returns (bool) { + function supportsModule(uint256 moduleTypeId) external pure returns (bool) { return moduleTypeId < 7; } @@ -265,7 +269,7 @@ abstract contract Kernel is ModuleManager, ExecutionManager { } } - function accountId() external view returns (string memory accountImplementationId) { + function accountId() external pure returns (string memory accountImplementationId) { return "kernel.v0.4"; } } diff --git a/src/core/HookManager.sol b/src/core/HookManager.sol index 8dd81c5c..e582c6fd 100644 --- a/src/core/HookManager.sol +++ b/src/core/HookManager.sol @@ -15,7 +15,7 @@ abstract contract HookManager { mapping(address => bool) enabled; } - function _hookStorage() internal view returns (HookStorage storage hs) { + function _hookStorage() internal pure returns (HookStorage storage hs) { bytes32 slot = HOOK_MANAGER_STORAGE_SLOT; assembly { hs.slot := slot @@ -29,21 +29,20 @@ abstract contract HookManager { _hookStorage().enabled[_hook] = true; } - function _uninstallHook(address _hook, bytes calldata _internalData, bool _uninstallSuccess) internal { + function _uninstallHook(address _hook, bytes calldata , bool ) internal { _hookStorage().enabled[_hook] = false; } - function _preHook(IHook _hook) internal returns (bytes memory context) { - require(address(_hook) != address(0), NotInstalled()); - if (address(_hook) != address(1)) { - context = _hook.preCheck(msg.sender, msg.value, msg.data); + function _preHook(IHook _hook, bytes calldata _data) internal returns (bytes memory context) { + if (address(_hook) != address(0)) { + context = _hook.preCheck(msg.sender, msg.value, _data); } } function _postHook(IHook _hook, bytes memory context) internal { // bool success, // bytes memory result - if (address(_hook) != address(1)) { + if (address(_hook) != address(0)) { _hook.postCheck(context); } } diff --git a/src/core/ModuleManager.sol b/src/core/ModuleManager.sol index 92f79b79..fefa7774 100644 --- a/src/core/ModuleManager.sol +++ b/src/core/ModuleManager.sol @@ -23,7 +23,7 @@ struct ModuleStorage { abstract contract ModuleManager is ValidationManager, ExecutorManager, HookManager, SelectorManager, ERC1271 { modifier executorHook() { IHook hook = _executorConfig(IExecutor(msg.sender)).hook; - bytes memory hookData = _preHook(hook); + bytes memory hookData = _preHook(hook, msg.data); _; _postHook(hook, hookData); } @@ -54,7 +54,7 @@ abstract contract ModuleManager is ValidationManager, ExecutorManager, HookManag || ValidationId.unwrap(_validationStorage().root) != bytes20(0); } - function _moduleStorage() internal view returns (ModuleStorage storage $) { + function _moduleStorage() internal pure returns (ModuleStorage storage $) { assembly { $.slot := MODULE_MANAGER_STORAGE_SLOT } diff --git a/src/core/ValidationManager.sol b/src/core/ValidationManager.sol index 81998be1..d6e8dc79 100644 --- a/src/core/ValidationManager.sol +++ b/src/core/ValidationManager.sol @@ -100,7 +100,7 @@ abstract contract ValidationManager { $.vType = VALIDATION_TYPE_ROOT; } - function _checkValidation(ValidationMode vMode, ValidationType vType, ValidationId vId) + function _checkValidation(ValidationType vType, ValidationId vId) internal view returns ( From f4c3fc4af9e404ca800f85b52c220bb6855aae19 Mon Sep 17 00:00:00 2001 From: leekt Date: Fri, 1 Aug 2025 00:24:42 +0900 Subject: [PATCH 044/121] validation hook --- snapshots/Kernel7702Test.json | 2 +- snapshots/KernelECDSATest.json | 4 +- snapshots/KernelTest.json | 4 +- src/Kernel.sol | 18 +++++- src/core/HookManager.sol | 6 +- src/core/ValidationManager.sol | 37 +++++++++--- src/lib/ERC1271.sol | 8 ++- src/types/Error.sol | 2 + src/types/Structs.sol | 2 + test/Kernel.t.sol | 102 +++++++++++++++++---------------- 10 files changed, 113 insertions(+), 72 deletions(-) diff --git a/snapshots/Kernel7702Test.json b/snapshots/Kernel7702Test.json index 4838133c..86c209ee 100644 --- a/snapshots/Kernel7702Test.json +++ b/snapshots/Kernel7702Test.json @@ -1,3 +1,3 @@ { - "Root - foo()": "166219" + "Root - foo()": "168609" } \ No newline at end of file diff --git a/snapshots/KernelECDSATest.json b/snapshots/KernelECDSATest.json index 07f52dde..8c0827bb 100644 --- a/snapshots/KernelECDSATest.json +++ b/snapshots/KernelECDSATest.json @@ -1,4 +1,4 @@ { - "Mock - deploy()": "158258", - "Root - foo()": "177829" + "Mock - deploy()": "158372", + "Root - foo()": "180218" } \ No newline at end of file diff --git a/snapshots/KernelTest.json b/snapshots/KernelTest.json index f19d54b1..75eed3c3 100644 --- a/snapshots/KernelTest.json +++ b/snapshots/KernelTest.json @@ -1,4 +1,4 @@ { - "Mock - deploy()": "159067", - "Root - foo()": "191695" + "Mock - deploy()": "159181", + "Root - foo()": "194084" } \ No newline at end of file diff --git a/src/Kernel.sol b/src/Kernel.sol index 6f80babf..1279f586 100644 --- a/src/Kernel.sol +++ b/src/Kernel.sol @@ -18,8 +18,6 @@ import "./types/Structs.sol"; abstract contract Kernel is ModuleManager, ExecutionManager { IEntryPoint immutable entryPoint; - IHook transient validationHook; - function _onlyEntryPointOrSelf() internal { require(msg.sender == address(entryPoint) || msg.sender == address(this), Unauthorized()); } @@ -80,6 +78,16 @@ abstract contract Kernel is ModuleManager, ExecutionManager { _install(sig.packages); signature = sig.userOpSignature; } + ValidationStorage storage $ = _validationStorage(); + + // check if the call data is allowed by the validationId + if ($.vInfo[vId].hook != address(0)) { + require(bytes4(userOp.callData[0:4]) == this.executeUserOp.selector && $.allowed[vId][bytes4(userOp.callData[4:])], UnauthorizedCallData()); + validationHook = IHook($.vInfo[vId].hook); + } else { + require(vType == VALIDATION_TYPE_ROOT || $.allowed[vId][bytes4(userOp.callData)], UnauthorizedCallData()); + } + (vId, validateUserOpFn) = _checkValidation(vType, vId); bytes32 opHash = isReplayable(vMode) ? Lib4337.chainAgnosticUserOpHash(msg.sender, userOp) : userOpHash; validationData = @@ -91,6 +99,12 @@ abstract contract Kernel is ModuleManager, ExecutionManager { _onlyEntryPointOrSelf(); bytes memory context = _preHook(validationHook, userOp.callData[4:]); (bool success, bytes memory ret) = address(this).delegatecall(userOp.callData[4:]); + // propagete the revert message + if (!success) { + assembly { + revert(add(ret, 0x20), mload(ret)) + } + } _postHook(validationHook, context); } diff --git a/src/core/HookManager.sol b/src/core/HookManager.sol index e582c6fd..0b6b04b9 100644 --- a/src/core/HookManager.sol +++ b/src/core/HookManager.sol @@ -29,12 +29,12 @@ abstract contract HookManager { _hookStorage().enabled[_hook] = true; } - function _uninstallHook(address _hook, bytes calldata , bool ) internal { + function _uninstallHook(address _hook, bytes calldata, bool) internal { _hookStorage().enabled[_hook] = false; } function _preHook(IHook _hook, bytes calldata _data) internal returns (bytes memory context) { - if (address(_hook) != address(0)) { + if (address(_hook) != address(1) && address(_hook) != address(0)) { context = _hook.preCheck(msg.sender, msg.value, _data); } } @@ -42,7 +42,7 @@ abstract contract HookManager { function _postHook(IHook _hook, bytes memory context) internal { // bool success, // bytes memory result - if (address(_hook) != address(0)) { + if (address(_hook) != address(1) && address(_hook) != address(0)) { _hook.postCheck(context); } } diff --git a/src/core/ValidationManager.sol b/src/core/ValidationManager.sol index d6e8dc79..30972a70 100644 --- a/src/core/ValidationManager.sol +++ b/src/core/ValidationManager.sol @@ -19,6 +19,7 @@ function parseNonce(uint256 nonce) pure returns (ValidationMode vMode, Validatio abstract contract ValidationManager { ValidationId transient installingPermission; + IHook transient validationHook; function root() external view returns (ValidationId) { ValidationStorage storage $ = _validationStorage(); @@ -30,18 +31,39 @@ abstract contract ValidationManager { return $.vInfo[vId]; } - function _validationStorage() internal view returns (ValidationStorage storage $) { + function _validationStorage() internal pure returns (ValidationStorage storage $) { assembly { $.slot := VALIDATION_MANAGER_STORAGE_SLOT } } + function _initializeValidation(ValidationId vId, bytes calldata _internalData) internal { + ValidationStorage storage $ = _validationStorage(); + + // if _internalData is empty, skip the initialization + if (_internalData.length == 0) { + return; + } + // if not, first 20 bytes is the hook address + address hook = address(bytes20(_internalData[0:20])); + $.vInfo[vId].hook = hook; + _internalData = _internalData[20:]; + + // then the rest is the allowed selectors + while (_internalData.length >= 4) { + bytes4 selector = bytes4(_internalData[0:4]); + $.allowed[vId][selector] = true; + _internalData = _internalData[4:]; + } + } + function _installValidator(address _validator, bytes calldata _internalData, bool _installSuccess) internal { require(_installSuccess, ModuleInstallFailed()); ValidationStorage storage $ = _validationStorage(); ValidationId vId = ValidationId.wrap(bytes20(_validator)); require($.vInfo[vId].vType == VALIDATION_TYPE_ROOT, OccupiedValidationId()); $.vInfo[vId].vType = VALIDATION_TYPE_VALIDATOR; + _initializeValidation(vId, _internalData); } function _installPolicy(address _policy, bytes calldata _internalData, bool _installSuccess) internal { @@ -67,6 +89,7 @@ abstract contract ValidationManager { require($.vType == ValidationType.wrap(0x00), "already taken"); installingPermission = vId; $.vType = VALIDATION_TYPE_PERMISSION; + _initializeValidation(vId, _internalData[20:]); } else { require(installingPermission == vId, "permissionId should be consistent"); } @@ -155,8 +178,6 @@ abstract contract ValidationManager { bytes calldata _signature ) internal view returns (uint256 validationData) { unchecked { - uint256 length = vInfo.policies.length + 1; - PermissionSignature calldata permissionSig; assembly { permissionSig := _signature.offset @@ -179,11 +200,11 @@ abstract contract ValidationManager { } function _validateUserOpFallback( - ValidationId vId, + ValidationId, bytes32 opHash, - PackedUserOperation memory op, + PackedUserOperation memory, bytes calldata userOpSignature - ) internal returns (uint256 validationData) { + ) internal virtual returns (uint256 validationData) { return _verifyFallbackSignature(opHash, userOpSignature) ? 0 : 1; } @@ -211,8 +232,6 @@ abstract contract ValidationManager { ) internal returns (uint256 validationData) { ValidationInfo storage vInfo = _validationStorage().vInfo[vId]; unchecked { - uint256 length = vInfo.policies.length + 1; - PermissionSignature calldata permissionSig; assembly { permissionSig := userOpSignature.offset @@ -232,7 +251,7 @@ abstract contract ValidationManager { } } - function _verifyFallbackSignature(bytes32 hash, bytes calldata sig) internal view virtual returns (bool) { + function _verifyFallbackSignature(bytes32, bytes calldata) internal view virtual returns (bool) { return false; } diff --git a/src/lib/ERC1271.sol b/src/lib/ERC1271.sol index 673cdd30..5e040d19 100644 --- a/src/lib/ERC1271.sol +++ b/src/lib/ERC1271.sol @@ -80,7 +80,9 @@ abstract contract ERC1271 is EIP712 { /// @dev Returns whether the `signature` is valid for the `hash. function _erc1271IsValidSignature(bytes32 hash, bytes calldata signature) internal view virtual returns (bool) { return _erc1271IsValidSignatureViaSafeCaller(hash, signature) - || _erc1271IsValidSignatureViaNestedEIP712(hash, signature) || _erc1271IsValidSignatureViaNestedEIP712Replayable(hash, signature) || _erc1271IsValidSignatureViaRPC(hash, signature); + || _erc1271IsValidSignatureViaNestedEIP712(hash, signature) + || _erc1271IsValidSignatureViaNestedEIP712Replayable(hash, signature) + || _erc1271IsValidSignatureViaRPC(hash, signature); } /// @dev Performs the signature validation without nested EIP-712 if the caller is @@ -256,7 +258,7 @@ abstract contract ERC1271 is EIP712 { if (t == uint256(0)) hash = _hashTypedData(hash); // `PersonalSign` workflow. result = _erc1271IsValidSignatureNowCalldata(hash, signature); } - + function _erc1271IsValidSignatureViaNestedEIP712Replayable(bytes32 hash, bytes calldata signature) internal view @@ -266,7 +268,7 @@ abstract contract ERC1271 is EIP712 { uint256 t = uint256(uint160(address(this))); // Forces the compiler to pop the variables after the scope, avoiding stack-too-deep. if (t != uint256(0)) { - (, string memory name, string memory version, /*chainId*/,address verifyingContract, bytes32 salt,) = + (, string memory name, string memory version, /*chainId*/, address verifyingContract, bytes32 salt,) = eip712Domain(); /// @solidity memory-safe-assembly assembly { diff --git a/src/types/Error.sol b/src/types/Error.sol index 2db479e3..4a8adcf6 100644 --- a/src/types/Error.sol +++ b/src/types/Error.sol @@ -26,3 +26,5 @@ error OccupiedValidationId(); error InvalidPermissionUninstallOrder(); error InvalidPermissionId(); error InvalidNonce(); + +error UnauthorizedCallData(); diff --git a/src/types/Structs.sol b/src/types/Structs.sol index af60cc9a..0e6de5da 100644 --- a/src/types/Structs.sol +++ b/src/types/Structs.sol @@ -19,11 +19,13 @@ struct ValidationInfo { ValidationType vType; address[] policies; address signer; + address hook; } struct ValidationStorage { ValidationId root; mapping(ValidationId vId => ValidationInfo) vInfo; + mapping(ValidationId vId => mapping(bytes4 selector => bool)) allowed; } struct Call { diff --git a/test/Kernel.t.sol b/test/Kernel.t.sol index 3d00cff6..5db47304 100644 --- a/test/Kernel.t.sol +++ b/test/Kernel.t.sol @@ -208,6 +208,7 @@ contract KernelTest is Test { } function encodeEnableValidatorSignature( + bytes4 selector, uint256 nonce, bool enableSuccess, bool replayable, @@ -215,13 +216,14 @@ contract KernelTest is Test { bytes memory userOpSig ) internal returns (bytes memory sig) { Install[] memory packages = new Install[](1); - packages[0] = Install({moduleType: 1, module: address(newValidator), moduleData: hex"", internalData: hex""}); + packages[0] = Install({moduleType: 1, module: address(newValidator), moduleData: hex"", internalData: abi.encodePacked(address(0), selector)}); sig = abi.encode( uint256(0), packages, enableSig(nonce, enableSuccess, replayable, packages, signEnable), userOpSig ); } function encodeEnablePermissionSignature( + bytes4 selector, uint256 nonce, bool enableSuccess, bool replayable, @@ -233,7 +235,7 @@ contract KernelTest is Test { moduleType: 5, module: address(policy), moduleData: hex"", - internalData: abi.encodePacked(permissionId) + internalData: abi.encodePacked(permissionId, address(0), selector) }); packages[1] = Install({ moduleType: 6, @@ -456,25 +458,25 @@ contract KernelTest is Test { ep.handleOps(ops, beneficiary); } - function test_userop_validator_use_root_if_notinstalled() external entryPointTest { - PackedUserOperation[] memory ops = new PackedUserOperation[](1); - ops[0] = PackedUserOperation({ - sender: address(kernel), - nonce: encodeNonce(false, false, false, bytes1(0x01), bytes20(address(newValidator))), - initCode: hex"", - callData: abi.encodeWithSelector( - Kernel.execute.selector, bytes32(0), abi.encodePacked(address(callee), uint256(0), MockCallee.foo.selector) - ), - accountGasLimits: bytes32(abi.encodePacked(uint128(1000000), uint128(1000000))), // TODO make this dynamic - preVerificationGas: 1000000, - gasFees: bytes32(abi.encodePacked(uint128(1), uint128(1))), - paymasterAndData: hex"", - signature: hex"" - }); - ops[0].signature = _rootSignUserOp(ops[0], true, false); - ep.handleOps(ops, beneficiary); - assertEq(callee.bar(), 1); - } + // function test_userop_validator_use_root_if_notinstalled() external entryPointTest { + // PackedUserOperation[] memory ops = new PackedUserOperation[](1); + // ops[0] = PackedUserOperation({ + // sender: address(kernel), + // nonce: encodeNonce(false, false, false, bytes1(0x01), bytes20(address(newValidator))), + // initCode: hex"", + // callData: abi.encodeWithSelector( + // Kernel.execute.selector, bytes32(0), abi.encodePacked(address(callee), uint256(0), MockCallee.foo.selector) + // ), + // accountGasLimits: bytes32(abi.encodePacked(uint128(1000000), uint128(1000000))), // TODO make this dynamic + // preVerificationGas: 1000000, + // gasFees: bytes32(abi.encodePacked(uint128(1), uint128(1))), + // paymasterAndData: hex"", + // signature: hex"" + // }); + // ops[0].signature = _rootSignUserOp(ops[0], true, false); + // ep.handleOps(ops, beneficiary); + // assertEq(callee.bar(), 1); + // } function test_userop_validator_enable() external entryPointTest { PackedUserOperation[] memory ops = new PackedUserOperation[](1); @@ -492,7 +494,7 @@ contract KernelTest is Test { signature: hex"" }); ops[0].signature = - encodeEnableValidatorSignature(0, true, false, _rootSignHash, _validatorSignUserOp(ops[0], true, false)); + encodeEnableValidatorSignature(Kernel.execute.selector, 0, true, false, _rootSignHash, _validatorSignUserOp(ops[0], true, false)); ep.handleOps(ops, beneficiary); assertEq(callee.bar(), 1); } @@ -513,7 +515,7 @@ contract KernelTest is Test { signature: hex"" }); ops[0].signature = - encodeEnableValidatorSignature(0, false, false, _rootSignHash, _validatorSignUserOp(ops[0], true, false)); + encodeEnableValidatorSignature(Kernel.execute.selector, 0, false, false, _rootSignHash, _validatorSignUserOp(ops[0], true, false)); vm.expectRevert(abi.encodeWithSelector(IEntryPoint.FailedOp.selector, 0, "AA24 signature error")); ep.handleOps(ops, beneficiary); } @@ -535,7 +537,7 @@ contract KernelTest is Test { }); ops[0].signature = - encodeEnableValidatorSignature(0, true, false, _rootSignHash, _validatorSignUserOp(ops[0], false, false)); + encodeEnableValidatorSignature(Kernel.execute.selector, 0, true, false, _rootSignHash, _validatorSignUserOp(ops[0], false, false)); vm.expectRevert(abi.encodeWithSelector(IEntryPoint.FailedOp.selector, 0, "AA24 signature error")); ep.handleOps(ops, beneficiary); } @@ -561,25 +563,25 @@ contract KernelTest is Test { ep.handleOps(ops, beneficiary); } - function test_userop_permission_use_root_if_notinstalled() external entryPointTest { - PackedUserOperation[] memory ops = new PackedUserOperation[](1); - ops[0] = PackedUserOperation({ - sender: address(kernel), - nonce: encodeNonce(false, false, false, bytes1(0x02), permissionId), - initCode: hex"", - callData: abi.encodeWithSelector( - Kernel.execute.selector, bytes32(0), abi.encodePacked(address(callee), uint256(0), MockCallee.foo.selector) - ), - accountGasLimits: bytes32(abi.encodePacked(uint128(1000000), uint128(1000000))), // TODO make this dynamic - preVerificationGas: 1000000, - gasFees: bytes32(abi.encodePacked(uint128(1), uint128(1))), - paymasterAndData: hex"", - signature: hex"" - }); - ops[0].signature = _rootSignUserOp(ops[0], true, false); - ep.handleOps(ops, beneficiary); - assertEq(callee.bar(), 1); - } + // function test_userop_permission_use_root_if_notinstalled() external entryPointTest { + // PackedUserOperation[] memory ops = new PackedUserOperation[](1); + // ops[0] = PackedUserOperation({ + // sender: address(kernel), + // nonce: encodeNonce(false, false, false, bytes1(0x02), permissionId), + // initCode: hex"", + // callData: abi.encodeWithSelector( + // Kernel.execute.selector, bytes32(0), abi.encodePacked(address(callee), uint256(0), MockCallee.foo.selector) + // ), + // accountGasLimits: bytes32(abi.encodePacked(uint128(1000000), uint128(1000000))), // TODO make this dynamic + // preVerificationGas: 1000000, + // gasFees: bytes32(abi.encodePacked(uint128(1), uint128(1))), + // paymasterAndData: hex"", + // signature: hex"" + // }); + // ops[0].signature = _rootSignUserOp(ops[0], true, false); + // ep.handleOps(ops, beneficiary); + // assertEq(callee.bar(), 1); + // } function test_userop_permission_enable() external entryPointTest { PackedUserOperation[] memory ops = new PackedUserOperation[](1); @@ -598,7 +600,7 @@ contract KernelTest is Test { }); ops[0].signature = - encodeEnablePermissionSignature(0, true, false, _rootSignHash, _permissionSignUserOp(ops[0], true, false)); + encodeEnablePermissionSignature(Kernel.execute.selector, 0, true, false, _rootSignHash, _permissionSignUserOp(ops[0], true, false)); ep.handleOps(ops, beneficiary); assertEq(callee.bar(), 1); } @@ -619,7 +621,7 @@ contract KernelTest is Test { signature: hex"" }); ops[0].signature = - encodeEnablePermissionSignature(0, false, false, _rootSignHash, _permissionSignUserOp(ops[0], true, false)); + encodeEnablePermissionSignature(Kernel.execute.selector, 0, false, false, _rootSignHash, _permissionSignUserOp(ops[0], true, false)); vm.expectRevert(abi.encodeWithSelector(IEntryPoint.FailedOp.selector, 0, "AA24 signature error")); ep.handleOps(ops, beneficiary); } @@ -640,7 +642,7 @@ contract KernelTest is Test { signature: hex"" }); ops[0].signature = - encodeEnablePermissionSignature(0, true, false, _rootSignHash, _permissionSignUserOp(ops[0], false, false)); + encodeEnablePermissionSignature(Kernel.execute.selector, 0, true, false, _rootSignHash, _permissionSignUserOp(ops[0], false, false)); vm.expectRevert(abi.encodeWithSelector(IEntryPoint.FailedOp.selector, 0, "AA24 signature error")); ep.handleOps(ops, beneficiary); } @@ -662,7 +664,7 @@ contract KernelTest is Test { }); permissionRevertIndex = 1; ops[0].signature = - encodeEnablePermissionSignature(0, true, false, _rootSignHash, _permissionSignUserOp(ops[0], false, false)); + encodeEnablePermissionSignature(Kernel.execute.selector, 0, true, false, _rootSignHash, _permissionSignUserOp(ops[0], false, false)); vm.expectRevert(abi.encodeWithSelector(IEntryPoint.FailedOp.selector, 0, "AA24 signature error")); ep.handleOps(ops, beneficiary); } @@ -1007,7 +1009,7 @@ contract KernelTest is Test { function test_install_validator() external unitTest { assertTrue(kernel.supportsModule(1)); ValidationId vId = ValidationId.wrap(bytes20(address(newValidator))); - kernel.installModule(1, address(newValidator), abi.encode(hex"deadbeef", "InternalData")); + kernel.installModule(1, address(newValidator), abi.encode(hex"deadbeef", hex"")); ValidationInfo memory vInfo = kernel.validationInfo(vId); assertTrue(vInfo.vType == VALIDATION_TYPE_VALIDATOR); bytes4 ret = kernel.isValidSignature( @@ -1019,10 +1021,10 @@ contract KernelTest is Test { function test_uninstall_validator() external unitTest { ValidationId vId = ValidationId.wrap(bytes20(address(newValidator))); - kernel.installModule(1, address(newValidator), abi.encode(hex"deadbeef", "InternalData")); + kernel.installModule(1, address(newValidator), abi.encode(hex"deadbeef", hex"")); ValidationInfo memory vInfo = kernel.validationInfo(vId); assertTrue(vInfo.vType == VALIDATION_TYPE_VALIDATOR); - kernel.uninstallModule(1, address(newValidator), abi.encode(hex"deadbeef", "InternalData")); + kernel.uninstallModule(1, address(newValidator), abi.encode(hex"deadbeef", hex"")); vInfo = kernel.validationInfo(vId); assertTrue(vInfo.vType == VALIDATION_TYPE_ROOT); } From 0bd65170c1a7440d6e5e143de786eb0b95518e64 Mon Sep 17 00:00:00 2001 From: leekt Date: Fri, 1 Aug 2025 00:57:26 +0900 Subject: [PATCH 045/121] updated --- src/Kernel.sol | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Kernel.sol b/src/Kernel.sol index 1279f586..d2d7ad01 100644 --- a/src/Kernel.sol +++ b/src/Kernel.sol @@ -138,11 +138,14 @@ abstract contract Kernel is ModuleManager, ExecutionManager { bytes4 selector = bytes4(msg.data[0:4]); SelectorConfig storage $ = _selectorConfig(selector); - if ($.target == address(0)) { + // if the selector is not initialized, revert + // if the selector is installed but hook is not set, only entrypoint can call it + if ($.target == address(0) || ($.hook == IHook(address(0)) && msg.sender != address(entryPoint))) { revert InvalidSelector(); } bytes memory hookData; - if (address($.hook) != address(0)) { + // explicitly set to address(1) to skip the hook while allowing anyone to call it + if (address($.hook) != address(0) && address($.hook) != address(1)) { hookData = _preHook($.hook, msg.data); } @@ -157,7 +160,7 @@ abstract contract Kernel is ModuleManager, ExecutionManager { } else { res = _getReturn(); } - if (address($.hook) != address(0)) { + if (address($.hook) != address(0) && address($.hook) != address(1)) { _postHook($.hook, hookData); } } From 19c971af0a18dbf5a168ea0910731a0c8776bbec Mon Sep 17 00:00:00 2001 From: leekt Date: Thu, 7 Aug 2025 15:17:17 +0900 Subject: [PATCH 046/121] remote push --- snapshots/KernelECDSATest.json | 2 +- snapshots/KernelTest.json | 2 +- src/Kernel7702.sol | 4 ++++ src/KernelFactory.sol | 34 ++++++++++++++++++++++++++++++++++ src/KernelUUPSECDSA.sol | 21 +++++++++++++++++++++ src/core/ModuleManager.sol | 2 +- 6 files changed, 62 insertions(+), 3 deletions(-) create mode 100644 src/KernelUUPSECDSA.sol diff --git a/snapshots/KernelECDSATest.json b/snapshots/KernelECDSATest.json index 8c0827bb..1da5360c 100644 --- a/snapshots/KernelECDSATest.json +++ b/snapshots/KernelECDSATest.json @@ -1,4 +1,4 @@ { - "Mock - deploy()": "158372", + "Mock - deploy()": "158491", "Root - foo()": "180218" } \ No newline at end of file diff --git a/snapshots/KernelTest.json b/snapshots/KernelTest.json index 75eed3c3..4a242f8a 100644 --- a/snapshots/KernelTest.json +++ b/snapshots/KernelTest.json @@ -1,4 +1,4 @@ { - "Mock - deploy()": "159181", + "Mock - deploy()": "159300", "Root - foo()": "194084" } \ No newline at end of file diff --git a/src/Kernel7702.sol b/src/Kernel7702.sol index 9daf515b..84e30074 100644 --- a/src/Kernel7702.sol +++ b/src/Kernel7702.sol @@ -10,4 +10,8 @@ contract Kernel7702 is Kernel { function _verifyFallbackSignature(bytes32 hash, bytes calldata sig) internal view override returns (bool) { return ECDSA.tryRecover(hash, sig) == address(this); } + + function _initialized() internal override view returns(bool) { + return true; + } } diff --git a/src/KernelFactory.sol b/src/KernelFactory.sol index d8f0ee26..39f660eb 100644 --- a/src/KernelFactory.sol +++ b/src/KernelFactory.sol @@ -12,6 +12,7 @@ contract KernelFactory { template = new KernelUUPS(_entryPoint); } + // Kernel UUPS function deploy(Install[] calldata initialPackages, uint256 nonce) external payable returns (Kernel) { bytes32 salt = keccak256(abi.encode(initialPackages, nonce)); (bool deployed, address account) = LibClone.createDeterministicERC1967(msg.value, address(template), salt); @@ -43,4 +44,37 @@ contract KernelFactory { bytes32 salt = keccak256(abi.encode(initialPackages, nonce)); return LibClone.predictDeterministicAddressERC1967(address(template), salt, address(this)); } + + // Kernel UUPS ECDSA fallback + function deployECDSA(address signer, Install[] calldata initialPackages, uint256 nonce) external payable returns (Kernel) { + bytes32 salt = keccak256(abi.encode(initialPackages, nonce)); + (bool deployed, address account) = LibClone.createDeterministicERC1967(msg.value, address(template), salt); + Kernel k = Kernel(payable(account)); + if (deployed) { + return k; + } + k.installModule(true, 0, initialPackages, hex""); + return k; + } + + function deployECDSAWithCall(address signer, Install[] calldata initialPackages, uint256 nonce, bytes calldata extraCall) + external + payable + returns (Kernel) + { + bytes32 salt = keccak256(abi.encode(initialPackages, nonce)); + (bool deployed, address account) = LibClone.createDeterministicERC1967(msg.value, address(template), salt); + Kernel k = Kernel(payable(account)); + if (!deployed) { + k.installModule(true, 0, initialPackages, hex""); + } + (bool success,) = address(k).call(extraCall); + require(success, "call failed"); + return k; + } + + function getECDSAAddress(address signer, Install[] calldata initialPackages, uint256 nonce) public view virtual returns (address) { + bytes32 salt = keccak256(abi.encode(initialPackages, nonce)); + return LibClone.predictDeterministicAddressERC1967(address(template), salt, address(this)); + } } diff --git a/src/KernelUUPSECDSA.sol b/src/KernelUUPSECDSA.sol new file mode 100644 index 00000000..d67f3afd --- /dev/null +++ b/src/KernelUUPSECDSA.sol @@ -0,0 +1,21 @@ +pragma solidity ^0.8.0; + +import {IEntryPoint} from "account-abstraction/interfaces/IEntryPoint.sol"; +import {Kernel} from "./Kernel.sol"; +import {KernelUUPS} from "./KernelUUPS.sol"; +import {ECDSA} from "solady/utils/ECDSA.sol"; +import {LibClone} from "solady/utils/LibClone.sol"; + +contract KernelUUPSECDSA is KernelUUPS { + constructor(IEntryPoint _entryPoint) KernelUUPS(_entryPoint) {} + + function _verifyFallbackSignature(bytes32 hash, bytes calldata sig) internal view override returns (bool) { + address signer = address(uint160(bytes20(LibClone.argsOnERC1967(address(this), 0, 20)))); + + return ECDSA.tryRecover(hash, sig) == signer; + } + + function _initialized() internal override view returns(bool) { + return true; + } +} diff --git a/src/core/ModuleManager.sol b/src/core/ModuleManager.sol index fefa7774..43ec9c8a 100644 --- a/src/core/ModuleManager.sol +++ b/src/core/ModuleManager.sol @@ -49,7 +49,7 @@ abstract contract ModuleManager is ValidationManager, ExecutorManager, HookManag return (uint256(key) << 64) + seq; } - function _initialized() internal view returns (bool) { + function _initialized() internal virtual view returns (bool) { return bytes3(address(this).code) == bytes3(0xef0100) || ValidationId.unwrap(_validationStorage().root) != bytes20(0); } From 13d202c67d36708395584d639de6e848d3cb81a4 Mon Sep 17 00:00:00 2001 From: leekt Date: Thu, 7 Aug 2025 21:09:28 +0900 Subject: [PATCH 047/121] ecdsa optimized impl --- snapshots/Kernel7702Test.json | 2 +- snapshots/KernelECDSATest.json | 4 +- snapshots/KernelImmutableECDSATest.json | 4 ++ snapshots/KernelTest.json | 4 +- src/Kernel.sol | 37 +++++++----- src/Kernel7702.sol | 2 +- src/KernelFactory.sol | 60 +++++++++++-------- ...UUPSECDSA.sol => KernelImmutableECDSA.sol} | 21 +++++-- src/KernelUUPS.sol | 3 +- src/core/ModuleManager.sol | 13 +++- src/types/Error.sol | 1 + test/Kernel.t.sol | 44 +++++++++----- test/KernelImmutableECDSA.t.sol | 43 +++++++++++++ 13 files changed, 168 insertions(+), 70 deletions(-) create mode 100644 snapshots/KernelImmutableECDSATest.json rename src/{KernelUUPSECDSA.sol => KernelImmutableECDSA.sol} (51%) create mode 100644 test/KernelImmutableECDSA.t.sol diff --git a/snapshots/Kernel7702Test.json b/snapshots/Kernel7702Test.json index 86c209ee..1038772c 100644 --- a/snapshots/Kernel7702Test.json +++ b/snapshots/Kernel7702Test.json @@ -1,3 +1,3 @@ { - "Root - foo()": "168609" + "Root - foo()": "168608" } \ No newline at end of file diff --git a/snapshots/KernelECDSATest.json b/snapshots/KernelECDSATest.json index 1da5360c..5aaeae3e 100644 --- a/snapshots/KernelECDSATest.json +++ b/snapshots/KernelECDSATest.json @@ -1,4 +1,4 @@ { - "Mock - deploy()": "158491", - "Root - foo()": "180218" + "Mock - deploy()": "158220", + "Root - foo()": "180217" } \ No newline at end of file diff --git a/snapshots/KernelImmutableECDSATest.json b/snapshots/KernelImmutableECDSATest.json new file mode 100644 index 00000000..8b21996e --- /dev/null +++ b/snapshots/KernelImmutableECDSATest.json @@ -0,0 +1,4 @@ +{ + "Mock - deploy()": "158220", + "Root - foo()": "169103" +} \ No newline at end of file diff --git a/snapshots/KernelTest.json b/snapshots/KernelTest.json index 4a242f8a..f13a4c04 100644 --- a/snapshots/KernelTest.json +++ b/snapshots/KernelTest.json @@ -1,4 +1,4 @@ { - "Mock - deploy()": "159300", - "Root - foo()": "194084" + "Mock - deploy()": "159029", + "Root - foo()": "194083" } \ No newline at end of file diff --git a/src/Kernel.sol b/src/Kernel.sol index d2d7ad01..dc248e87 100644 --- a/src/Kernel.sol +++ b/src/Kernel.sol @@ -39,6 +39,20 @@ abstract contract Kernel is ModuleManager, ExecutionManager { bytes userOpSignature; } + function initialize(Install[] calldata packages) external { + require(!_initialized(), InvalidInitialization()); + // this is initialize + // require first package to be the root validator + _initialize(packages); + } + + function _initialize(Install[] calldata packages) internal virtual { + require(packages.length > 0); + Install calldata root = packages[0]; + _install(packages); + _setRoot(root); + } + function validateUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash, uint256 missingAccountFunds) external payable @@ -82,7 +96,11 @@ abstract contract Kernel is ModuleManager, ExecutionManager { // check if the call data is allowed by the validationId if ($.vInfo[vId].hook != address(0)) { - require(bytes4(userOp.callData[0:4]) == this.executeUserOp.selector && $.allowed[vId][bytes4(userOp.callData[4:])], UnauthorizedCallData()); + require( + bytes4(userOp.callData[0:4]) == this.executeUserOp.selector + && $.allowed[vId][bytes4(userOp.callData[4:])], + UnauthorizedCallData() + ); validationHook = IHook($.vInfo[vId].hook); } else { require(vType == VALIDATION_TYPE_ROOT || $.allowed[vId][bytes4(userOp.callData)], UnauthorizedCallData()); @@ -208,20 +226,9 @@ abstract contract Kernel is ModuleManager, ExecutionManager { function installModule(bool replayable, uint256 nonce, Install[] calldata packages, bytes calldata signature) external { - if (_initialized()) { - // if 7702 or already initialized, use root signature to install module - require( - _verifyInstallSignature(replayable, nonce, packages, signature), InstallSignatureVerificationFailed() - ); - _install(packages); - } else { - // this is initialize - // require first package to be the root validator - require(packages.length > 0); - Install calldata root = packages[0]; - _install(packages); - _setRoot(root); - } + // if 7702 or already initialized, use root signature to install module + require(_verifyInstallSignature(replayable, nonce, packages, signature), InstallSignatureVerificationFailed()); + _install(packages); } fallback(bytes calldata) external payable returns (bytes memory) { diff --git a/src/Kernel7702.sol b/src/Kernel7702.sol index 84e30074..e286e45f 100644 --- a/src/Kernel7702.sol +++ b/src/Kernel7702.sol @@ -11,7 +11,7 @@ contract Kernel7702 is Kernel { return ECDSA.tryRecover(hash, sig) == address(this); } - function _initialized() internal override view returns(bool) { + function _statelessInitializeCheck() internal view override returns (bool) { return true; } } diff --git a/src/KernelFactory.sol b/src/KernelFactory.sol index 39f660eb..0c8b7ee5 100644 --- a/src/KernelFactory.sol +++ b/src/KernelFactory.sol @@ -2,25 +2,28 @@ pragma solidity ^0.8.0; import {Kernel, Install} from "./Kernel.sol"; import {KernelUUPS} from "./KernelUUPS.sol"; +import {KernelImmutableECDSA} from "./KernelImmutableECDSA.sol"; import {LibClone} from "solady/utils/LibClone.sol"; import {IEntryPoint} from "account-abstraction/interfaces/IEntryPoint.sol"; contract KernelFactory { - KernelUUPS public immutable template; + KernelUUPS public immutable uups; + KernelImmutableECDSA public immutable immutableECDSA; constructor(IEntryPoint _entryPoint) { - template = new KernelUUPS(_entryPoint); + uups = new KernelUUPS(_entryPoint); + immutableECDSA = new KernelImmutableECDSA(_entryPoint); } // Kernel UUPS function deploy(Install[] calldata initialPackages, uint256 nonce) external payable returns (Kernel) { bytes32 salt = keccak256(abi.encode(initialPackages, nonce)); - (bool deployed, address account) = LibClone.createDeterministicERC1967(msg.value, address(template), salt); + (bool deployed, address account) = LibClone.createDeterministicERC1967(msg.value, address(uups), salt); Kernel k = Kernel(payable(account)); if (deployed) { return k; } - k.installModule(true, 0, initialPackages, hex""); + k.initialize(initialPackages); return k; } @@ -30,10 +33,10 @@ contract KernelFactory { returns (Kernel) { bytes32 salt = keccak256(abi.encode(initialPackages, nonce)); - (bool deployed, address account) = LibClone.createDeterministicERC1967(msg.value, address(template), salt); + (bool deployed, address account) = LibClone.createDeterministicERC1967(msg.value, address(uups), salt); Kernel k = Kernel(payable(account)); if (!deployed) { - k.installModule(true, 0, initialPackages, hex""); + k.initialize(initialPackages); } (bool success,) = address(k).call(extraCall); require(success, "call failed"); @@ -42,39 +45,48 @@ contract KernelFactory { function getAddress(Install[] calldata initialPackages, uint256 nonce) public view virtual returns (address) { bytes32 salt = keccak256(abi.encode(initialPackages, nonce)); - return LibClone.predictDeterministicAddressERC1967(address(template), salt, address(this)); + return LibClone.predictDeterministicAddressERC1967(address(uups), salt, address(this)); } // Kernel UUPS ECDSA fallback - function deployECDSA(address signer, Install[] calldata initialPackages, uint256 nonce) external payable returns (Kernel) { + function deployECDSA(address signer, Install[] calldata initialPackages, uint256 nonce) + external + payable + returns (Kernel) + { bytes32 salt = keccak256(abi.encode(initialPackages, nonce)); - (bool deployed, address account) = LibClone.createDeterministicERC1967(msg.value, address(template), salt); + (, address account) = + LibClone.createDeterministicERC1967(address(immutableECDSA), abi.encodePacked(signer), salt); Kernel k = Kernel(payable(account)); - if (deployed) { - return k; - } - k.installModule(true, 0, initialPackages, hex""); + k.initialize(initialPackages); return k; } - function deployECDSAWithCall(address signer, Install[] calldata initialPackages, uint256 nonce, bytes calldata extraCall) - external - payable - returns (Kernel) - { + function deployECDSAWithCall( + address signer, + Install[] calldata initialPackages, + uint256 nonce, + bytes calldata extraCall + ) external payable returns (Kernel) { bytes32 salt = keccak256(abi.encode(initialPackages, nonce)); - (bool deployed, address account) = LibClone.createDeterministicERC1967(msg.value, address(template), salt); + (, address account) = + LibClone.createDeterministicERC1967(address(immutableECDSA), abi.encodePacked(signer), salt); Kernel k = Kernel(payable(account)); - if (!deployed) { - k.installModule(true, 0, initialPackages, hex""); - } + k.initialize(initialPackages); (bool success,) = address(k).call(extraCall); require(success, "call failed"); return k; } - function getECDSAAddress(address signer, Install[] calldata initialPackages, uint256 nonce) public view virtual returns (address) { + function getECDSAAddress(address signer, Install[] calldata initialPackages, uint256 nonce) + public + view + virtual + returns (address) + { bytes32 salt = keccak256(abi.encode(initialPackages, nonce)); - return LibClone.predictDeterministicAddressERC1967(address(template), salt, address(this)); + return LibClone.predictDeterministicAddressERC1967( + address(immutableECDSA), abi.encodePacked(signer), salt, address(this) + ); } } diff --git a/src/KernelUUPSECDSA.sol b/src/KernelImmutableECDSA.sol similarity index 51% rename from src/KernelUUPSECDSA.sol rename to src/KernelImmutableECDSA.sol index d67f3afd..925f9879 100644 --- a/src/KernelUUPSECDSA.sol +++ b/src/KernelImmutableECDSA.sol @@ -5,17 +5,28 @@ import {Kernel} from "./Kernel.sol"; import {KernelUUPS} from "./KernelUUPS.sol"; import {ECDSA} from "solady/utils/ECDSA.sol"; import {LibClone} from "solady/utils/LibClone.sol"; +import {Install} from "./core/ModuleManager.sol"; -contract KernelUUPSECDSA is KernelUUPS { +contract KernelImmutableECDSA is KernelUUPS { constructor(IEntryPoint _entryPoint) KernelUUPS(_entryPoint) {} function _verifyFallbackSignature(bytes32 hash, bytes calldata sig) internal view override returns (bool) { address signer = address(uint160(bytes20(LibClone.argsOnERC1967(address(this), 0, 20)))); - return ECDSA.tryRecover(hash, sig) == signer; + if (ECDSA.tryRecover(hash, sig) == signer) { + return true; + } + if (ECDSA.tryRecover(ECDSA.toEthSignedMessageHash(hash), sig) == signer) { + return true; + } + return false; } - - function _initialized() internal override view returns(bool) { - return true; + + function _statelessInitializeCheck() internal view override returns (bool) { + return false; + } + + function _initialize(Install[] calldata packages) internal override initializer { + _install(packages); } } diff --git a/src/KernelUUPS.sol b/src/KernelUUPS.sol index d5de929f..5236a13c 100644 --- a/src/KernelUUPS.sol +++ b/src/KernelUUPS.sol @@ -3,8 +3,9 @@ pragma solidity ^0.8.0; import {IEntryPoint} from "account-abstraction/interfaces/IEntryPoint.sol"; import {Kernel} from "./Kernel.sol"; import {UUPSUpgradeable} from "solady/utils/UUPSUpgradeable.sol"; +import {Initializable} from "solady/utils/Initializable.sol"; -contract KernelUUPS is Kernel, UUPSUpgradeable { +contract KernelUUPS is Kernel, UUPSUpgradeable, Initializable { constructor(IEntryPoint _entryPoint) Kernel(_entryPoint) {} function _authorizeUpgrade(address) internal override { diff --git a/src/core/ModuleManager.sol b/src/core/ModuleManager.sol index 43ec9c8a..1150b0c3 100644 --- a/src/core/ModuleManager.sol +++ b/src/core/ModuleManager.sol @@ -49,9 +49,16 @@ abstract contract ModuleManager is ValidationManager, ExecutorManager, HookManag return (uint256(key) << 64) + seq; } - function _initialized() internal virtual view returns (bool) { - return bytes3(address(this).code) == bytes3(0xef0100) - || ValidationId.unwrap(_validationStorage().root) != bytes20(0); + function _initialized() internal view virtual returns (bool) { + return _statelessInitializeCheck() || _statefulInitializeCheck(); + } + + function _statelessInitializeCheck() internal view virtual returns (bool) { + return bytes3(address(this).code) == bytes3(0xef0100); + } + + function _statefulInitializeCheck() internal view virtual returns (bool) { + return ValidationId.unwrap(_validationStorage().root) != bytes20(0); } function _moduleStorage() internal pure returns (ModuleStorage storage $) { diff --git a/src/types/Error.sol b/src/types/Error.sol index 4a8adcf6..6ab27214 100644 --- a/src/types/Error.sol +++ b/src/types/Error.sol @@ -26,5 +26,6 @@ error OccupiedValidationId(); error InvalidPermissionUninstallOrder(); error InvalidPermissionId(); error InvalidNonce(); +error InvalidInitialization(); error UnauthorizedCallData(); diff --git a/test/Kernel.t.sol b/test/Kernel.t.sol index 5db47304..57e4bb7d 100644 --- a/test/Kernel.t.sol +++ b/test/Kernel.t.sol @@ -216,7 +216,12 @@ contract KernelTest is Test { bytes memory userOpSig ) internal returns (bytes memory sig) { Install[] memory packages = new Install[](1); - packages[0] = Install({moduleType: 1, module: address(newValidator), moduleData: hex"", internalData: abi.encodePacked(address(0), selector)}); + packages[0] = Install({ + moduleType: 1, + module: address(newValidator), + moduleData: hex"", + internalData: abi.encodePacked(address(0), selector) + }); sig = abi.encode( uint256(0), packages, enableSig(nonce, enableSuccess, replayable, packages, signEnable), userOpSig ); @@ -270,7 +275,7 @@ contract KernelTest is Test { function test_codesize() external { vm.skip(true); - address implementation = address(factory.template()); + address implementation = address(factory.uups()); console.log("Code size :", implementation.code.length); require(implementation.code.length <= 24576, "Code too big"); console.log("space left :", 24576 - implementation.code.length); @@ -493,8 +498,9 @@ contract KernelTest is Test { paymasterAndData: hex"", signature: hex"" }); - ops[0].signature = - encodeEnableValidatorSignature(Kernel.execute.selector, 0, true, false, _rootSignHash, _validatorSignUserOp(ops[0], true, false)); + ops[0].signature = encodeEnableValidatorSignature( + Kernel.execute.selector, 0, true, false, _rootSignHash, _validatorSignUserOp(ops[0], true, false) + ); ep.handleOps(ops, beneficiary); assertEq(callee.bar(), 1); } @@ -514,8 +520,9 @@ contract KernelTest is Test { paymasterAndData: hex"", signature: hex"" }); - ops[0].signature = - encodeEnableValidatorSignature(Kernel.execute.selector, 0, false, false, _rootSignHash, _validatorSignUserOp(ops[0], true, false)); + ops[0].signature = encodeEnableValidatorSignature( + Kernel.execute.selector, 0, false, false, _rootSignHash, _validatorSignUserOp(ops[0], true, false) + ); vm.expectRevert(abi.encodeWithSelector(IEntryPoint.FailedOp.selector, 0, "AA24 signature error")); ep.handleOps(ops, beneficiary); } @@ -536,8 +543,9 @@ contract KernelTest is Test { signature: hex"" }); - ops[0].signature = - encodeEnableValidatorSignature(Kernel.execute.selector, 0, true, false, _rootSignHash, _validatorSignUserOp(ops[0], false, false)); + ops[0].signature = encodeEnableValidatorSignature( + Kernel.execute.selector, 0, true, false, _rootSignHash, _validatorSignUserOp(ops[0], false, false) + ); vm.expectRevert(abi.encodeWithSelector(IEntryPoint.FailedOp.selector, 0, "AA24 signature error")); ep.handleOps(ops, beneficiary); } @@ -599,8 +607,9 @@ contract KernelTest is Test { signature: hex"" }); - ops[0].signature = - encodeEnablePermissionSignature(Kernel.execute.selector, 0, true, false, _rootSignHash, _permissionSignUserOp(ops[0], true, false)); + ops[0].signature = encodeEnablePermissionSignature( + Kernel.execute.selector, 0, true, false, _rootSignHash, _permissionSignUserOp(ops[0], true, false) + ); ep.handleOps(ops, beneficiary); assertEq(callee.bar(), 1); } @@ -620,8 +629,9 @@ contract KernelTest is Test { paymasterAndData: hex"", signature: hex"" }); - ops[0].signature = - encodeEnablePermissionSignature(Kernel.execute.selector, 0, false, false, _rootSignHash, _permissionSignUserOp(ops[0], true, false)); + ops[0].signature = encodeEnablePermissionSignature( + Kernel.execute.selector, 0, false, false, _rootSignHash, _permissionSignUserOp(ops[0], true, false) + ); vm.expectRevert(abi.encodeWithSelector(IEntryPoint.FailedOp.selector, 0, "AA24 signature error")); ep.handleOps(ops, beneficiary); } @@ -641,8 +651,9 @@ contract KernelTest is Test { paymasterAndData: hex"", signature: hex"" }); - ops[0].signature = - encodeEnablePermissionSignature(Kernel.execute.selector, 0, true, false, _rootSignHash, _permissionSignUserOp(ops[0], false, false)); + ops[0].signature = encodeEnablePermissionSignature( + Kernel.execute.selector, 0, true, false, _rootSignHash, _permissionSignUserOp(ops[0], false, false) + ); vm.expectRevert(abi.encodeWithSelector(IEntryPoint.FailedOp.selector, 0, "AA24 signature error")); ep.handleOps(ops, beneficiary); } @@ -663,8 +674,9 @@ contract KernelTest is Test { signature: hex"" }); permissionRevertIndex = 1; - ops[0].signature = - encodeEnablePermissionSignature(Kernel.execute.selector, 0, true, false, _rootSignHash, _permissionSignUserOp(ops[0], false, false)); + ops[0].signature = encodeEnablePermissionSignature( + Kernel.execute.selector, 0, true, false, _rootSignHash, _permissionSignUserOp(ops[0], false, false) + ); vm.expectRevert(abi.encodeWithSelector(IEntryPoint.FailedOp.selector, 0, "AA24 signature error")); ep.handleOps(ops, beneficiary); } diff --git a/test/KernelImmutableECDSA.t.sol b/test/KernelImmutableECDSA.t.sol new file mode 100644 index 00000000..98a12ef0 --- /dev/null +++ b/test/KernelImmutableECDSA.t.sol @@ -0,0 +1,43 @@ +pragma solidity ^0.8.0; + +import "./Kernel.t.sol"; +import {Lib4337} from "src/lib/Lib4337.sol"; +import {ECDSAValidator} from "./mock/ECDSAValidator.sol"; + +contract KernelImmutableECDSATest is KernelTest { + address owner; + uint256 ownerKey; + + function _initialize() internal override { + (owner, ownerKey) = makeAddrAndKey("Owner"); + rootValidator = new ECDSAValidator(); + rootValidatorData = abi.encodePacked(owner); + Install[] memory pkgs = new Install[](0); + kernel = factory.deployECDSA(owner, pkgs, 0); + vm.deal(address(kernel), 1e18); + + vm.startPrank(address(ep)); + kernel.installModule(2, executor, abi.encode(hex"", "")); + vm.stopPrank(); + } + + function _rootSignUserOp(PackedUserOperation memory op, bool success, bool replay) + internal + override + returns (bytes memory sig) + { + bytes32 hash = replay ? Lib4337.chainAgnosticUserOpHash(address(ep), op) : ep.getUserOpHash(op); + return _rootSignHash(hash, success); + } + + function _rootSignHash(bytes32 hash, bool success) internal override returns (bytes memory sig) { + console.log("Owner :", owner); + console.log("Code :"); + console.logBytes(address(kernel).code); + if (!success) { + hash = keccak256(abi.encodePacked(hash)); + } + (uint8 v, bytes32 r, bytes32 s) = vm.sign(ownerKey, hash); + return abi.encodePacked(r, s, v); + } +} From 89779fe063a70dcb7d481c3eca45e75e06b82122 Mon Sep 17 00:00:00 2001 From: leekt Date: Thu, 7 Aug 2025 21:15:51 +0900 Subject: [PATCH 048/121] updated to get implementation as args --- src/KernelFactory.sol | 6 +++--- test/Kernel.t.sol | 7 ++++++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/KernelFactory.sol b/src/KernelFactory.sol index 0c8b7ee5..75b4418f 100644 --- a/src/KernelFactory.sol +++ b/src/KernelFactory.sol @@ -10,9 +10,9 @@ contract KernelFactory { KernelUUPS public immutable uups; KernelImmutableECDSA public immutable immutableECDSA; - constructor(IEntryPoint _entryPoint) { - uups = new KernelUUPS(_entryPoint); - immutableECDSA = new KernelImmutableECDSA(_entryPoint); + constructor(KernelUUPS _uups, KernelImmutableECDSA _immutableECDSA) { + uups = _uups; + immutableECDSA = _immutableECDSA; } // Kernel UUPS diff --git a/test/Kernel.t.sol b/test/Kernel.t.sol index 57e4bb7d..cc75a93d 100644 --- a/test/Kernel.t.sol +++ b/test/Kernel.t.sol @@ -9,6 +9,8 @@ import {KernelUUPS} from "src/KernelUUPS.sol"; import {KernelHelper} from "src/KernelHelper.sol"; import {SelectorManager} from "src/core/SelectorManager.sol"; import {KernelFactory} from "src/KernelFactory.sol"; +import {KernelUUPS} from "src/KernelUUPS.sol"; +import {KernelImmutableECDSA} from "src/KernelImmutableECDSA.sol"; import {LibERC7579} from "solady/accounts/LibERC7579.sol"; import {LibString} from "solady/utils/LibString.sol"; import {Install} from "src/types/Structs.sol"; @@ -98,7 +100,10 @@ contract KernelTest is Test { function setUp() external { ep = EntryPointLib.deploy(); - factory = new KernelFactory(ep); + + KernelUUPS uups = new KernelUUPS(ep); + KernelImmutableECDSA immutableECDSA = new KernelImmutableECDSA(ep); + factory = new KernelFactory(uups, immutableECDSA); helper = new KernelHelper(); newValidator = new MockValidator(); callee = new MockCallee(); From 9a81b95eac2630a63333aed16c63becf0658de65 Mon Sep 17 00:00:00 2001 From: leekt Date: Sat, 9 Aug 2025 02:26:37 +0900 Subject: [PATCH 049/121] check --- src/KernelFactory.sol | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/KernelFactory.sol b/src/KernelFactory.sol index 75b4418f..b286adc2 100644 --- a/src/KernelFactory.sol +++ b/src/KernelFactory.sol @@ -15,6 +15,25 @@ contract KernelFactory { immutableECDSA = _immutableECDSA; } + function checkInitialized(address account, bytes calldata initData) external view returns (bool) { + bytes4 selector = bytes4(initData[0:4]); + ( /*replayable*/ , /*nonce*/, Install[] memory packages, /*sig*/ ) = + abi.decode(initData, (bool, uint256, Install[], bytes)); + + // naively check if the package has been installed by only checking the nonce + for (uint256 i = 0; i < packages.length; i++) { + Install memory p = packages[i]; + uint256 n = p.nonce; + uint192 key = uint192(p.nonce >> 8); + uint64 seq = uint64(p.nonce); + + if (Kernel(account).nonce(key) <= seq) { + return false; + } + } + return true; + } + // Kernel UUPS function deploy(Install[] calldata initialPackages, uint256 nonce) external payable returns (Kernel) { bytes32 salt = keccak256(abi.encode(initialPackages, nonce)); From 1013f042a2a7ebe4757a4f5bf0e336b806b9a7fa Mon Sep 17 00:00:00 2001 From: leekt Date: Thu, 14 Aug 2025 19:47:54 +0900 Subject: [PATCH 050/121] fix: use isModuleInstalled properly --- src/KernelFactory.sol | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/KernelFactory.sol b/src/KernelFactory.sol index b286adc2..e743a7aa 100644 --- a/src/KernelFactory.sol +++ b/src/KernelFactory.sol @@ -20,14 +20,16 @@ contract KernelFactory { ( /*replayable*/ , /*nonce*/, Install[] memory packages, /*sig*/ ) = abi.decode(initData, (bool, uint256, Install[], bytes)); - // naively check if the package has been installed by only checking the nonce + // naively check if the package has been installed, does not guarantee if proper internalData is used for (uint256 i = 0; i < packages.length; i++) { Install memory p = packages[i]; - uint256 n = p.nonce; - uint192 key = uint192(p.nonce >> 8); - uint64 seq = uint64(p.nonce); - if (Kernel(account).nonce(key) <= seq) { + bytes memory context; + if(p.moduleType == 5 || p.moduleType == 6) { + context = abi.encodePacked(bytes20(p.internalData)); + } + + if (Kernel(payable(account)).isModuleInstalled(p.moduleType, p.module, context)) { return false; } } From 4b7c38901b0a47faf31c9c2a071f95ca02083209 Mon Sep 17 00:00:00 2001 From: leekt Date: Thu, 14 Aug 2025 19:48:03 +0900 Subject: [PATCH 051/121] fmt --- src/KernelFactory.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/KernelFactory.sol b/src/KernelFactory.sol index e743a7aa..be251184 100644 --- a/src/KernelFactory.sol +++ b/src/KernelFactory.sol @@ -25,7 +25,7 @@ contract KernelFactory { Install memory p = packages[i]; bytes memory context; - if(p.moduleType == 5 || p.moduleType == 6) { + if (p.moduleType == 5 || p.moduleType == 6) { context = abi.encodePacked(bytes20(p.internalData)); } From b8e5837d3dbd86923c76f908d67c7a44fdfcaead Mon Sep 17 00:00:00 2001 From: leekt Date: Thu, 14 Aug 2025 19:56:37 +0900 Subject: [PATCH 052/121] fix: use proper boolean --- snapshots/KernelECDSATest.json | 2 +- snapshots/KernelImmutableECDSATest.json | 2 +- snapshots/KernelTest.json | 2 +- src/KernelFactory.sol | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/snapshots/KernelECDSATest.json b/snapshots/KernelECDSATest.json index 5aaeae3e..e3b1a328 100644 --- a/snapshots/KernelECDSATest.json +++ b/snapshots/KernelECDSATest.json @@ -1,4 +1,4 @@ { - "Mock - deploy()": "158220", + "Mock - deploy()": "158293", "Root - foo()": "180217" } \ No newline at end of file diff --git a/snapshots/KernelImmutableECDSATest.json b/snapshots/KernelImmutableECDSATest.json index 8b21996e..723d5d9e 100644 --- a/snapshots/KernelImmutableECDSATest.json +++ b/snapshots/KernelImmutableECDSATest.json @@ -1,4 +1,4 @@ { - "Mock - deploy()": "158220", + "Mock - deploy()": "158293", "Root - foo()": "169103" } \ No newline at end of file diff --git a/snapshots/KernelTest.json b/snapshots/KernelTest.json index f13a4c04..993bba0e 100644 --- a/snapshots/KernelTest.json +++ b/snapshots/KernelTest.json @@ -1,4 +1,4 @@ { - "Mock - deploy()": "159029", + "Mock - deploy()": "159102", "Root - foo()": "194083" } \ No newline at end of file diff --git a/src/KernelFactory.sol b/src/KernelFactory.sol index be251184..5df4a528 100644 --- a/src/KernelFactory.sol +++ b/src/KernelFactory.sol @@ -29,7 +29,7 @@ contract KernelFactory { context = abi.encodePacked(bytes20(p.internalData)); } - if (Kernel(payable(account)).isModuleInstalled(p.moduleType, p.module, context)) { + if (!Kernel(payable(account)).isModuleInstalled(p.moduleType, p.module, context)) { return false; } } From e1c51b25d77ca6518aebc6f6d3623d6655708456 Mon Sep 17 00:00:00 2001 From: leekt Date: Wed, 24 Sep 2025 16:31:46 +0900 Subject: [PATCH 053/121] test: added erc1271 for 7702 --- test/Kernel7702.t.sol | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/Kernel7702.t.sol b/test/Kernel7702.t.sol index 9a4b81cd..9de376f1 100644 --- a/test/Kernel7702.t.sol +++ b/test/Kernel7702.t.sol @@ -39,4 +39,10 @@ contract Kernel7702Test is KernelTest { (uint8 v, bytes32 r, bytes32 s) = vm.sign(ownerKey, hash); return abi.encodePacked(r, s, v); } + + function test_erc1271() external { + bytes32 hash = bytes32(vm.randomBytes(32)); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(ownerKey, hash); + kernel.isValidSignature(hash, abi.encodePacked(r,s,v)); + } } From 2a2a6a7c577c896c2e0513ca79095ee6689cc464 Mon Sep 17 00:00:00 2001 From: leekt Date: Wed, 24 Sep 2025 23:23:59 +0900 Subject: [PATCH 054/121] separated kernel test base --- test/Kernel.t.sol | 262 +--------------------------------- test/KernelTestBase.sol | 219 ++++++++++++++++++++++++++++ test/mock/MockCallee.sol | 23 +-- test/mock/MockContractEth.sol | 11 ++ 4 files changed, 247 insertions(+), 268 deletions(-) create mode 100644 test/KernelTestBase.sol create mode 100644 test/mock/MockContractEth.sol diff --git a/test/Kernel.t.sol b/test/Kernel.t.sol index cc75a93d..7f373293 100644 --- a/test/Kernel.t.sol +++ b/test/Kernel.t.sol @@ -23,6 +23,8 @@ import {MockSigner} from "./mock/MockSigner.sol"; import {MockERC721} from "./mock/MockERC721.sol"; import {MockERC1155} from "./mock/MockERC1155.sol"; import {MockKernel} from "./mock/MockKernel.sol"; +import {MockCallee} from "./mock/MockCallee.sol"; +import {MockContractETH} from "./mock/MockContractETH.sol"; import {IHook, IValidator} from "src/interfaces/IERC7579Modules.sol"; import {CallType} from "src/types/Types.sol"; import "src/types/Constants.sol"; @@ -30,74 +32,9 @@ import "forge-std/console.sol"; import "src/types/Error.sol"; import "src/types/Events.sol"; import "src/types/Structs.sol"; +import {KernelTestBase} from "./KernelTestBase.sol"; -contract MockCallee { - uint256 public bar; - string public data; - - event Lorem(); - - error Haha(); - - function foo() external { - bar++; - emit Lorem(); - } - - function lorem() external { - data = "lorem ipsum"; - } - - function forceRevert() external { - revert Haha(); - } -} - -contract MockContractETH { - function useTransfer(address payable recipient, uint256 v) external { - recipient.transfer(v); - } - - function useSend(address payable recipient, uint256 v) external { - require(recipient.send(v), "send failed"); - } -} - -contract KernelTest is Test { - IEntryPoint ep; - KernelFactory factory; - IValidator rootValidator; - bytes rootValidatorData; - MockValidator newValidator; - Kernel kernel; - MockCallee callee; - MockFallback mockFallback; - address executor; - address payable beneficiary; - MockPolicy policy; - MockSigner signer; - bytes20 permissionId; - uint256 permissionRevertIndex; - KernelHelper helper; - - bool is7702; - - modifier unitTest() { - vm.startPrank(address(ep)); - _; - vm.stopPrank(); - } - - modifier unitTestExecutor() { - vm.startPrank(address(executor)); - _; - vm.stopPrank(); - } - - modifier entryPointTest() { - _; - } - +contract KernelTest is KernelTestBase { function setUp() external { ep = EntryPointLib.deploy(); @@ -117,7 +54,7 @@ contract KernelTest is Test { _initialize(); } - function _initialize() internal virtual { + function _initialize() internal virtual override { rootValidator = new MockValidator(); rootValidatorData = hex""; Install[] memory pkgs = new Install[](1); @@ -130,154 +67,6 @@ contract KernelTest is Test { vm.stopPrank(); } - function _rootSignUserOp(PackedUserOperation memory op, bool success, bool replay) - internal - virtual - returns (bytes memory sig) - { - MockValidator(address(rootValidator)).sudoSetSuccess(success); - return hex""; - } - - function _rootSignHash(bytes32 hash, bool success) internal virtual returns (bytes memory sig) { - if (success) { - MockValidator(address(rootValidator)).sudoSetValidSig(hex""); - } - return hex""; - } - - function _validatorSignUserOp(PackedUserOperation memory op, bool success, bool replay) - internal - virtual - returns (bytes memory sig) - { - newValidator.sudoSetSuccess(success); - return hex""; - } - - function _validatorSignHash(bytes32 hash, bool success) internal virtual returns (bytes memory sig) { - if (success) { - newValidator.sudoSetValidSig(hex""); - } - return hex""; - } - - function _permissionSignUserOp(PackedUserOperation memory op, bool success, bool replay) - internal - virtual - returns (bytes memory sig) - { - bytes[] memory signatures = new bytes[](2); - signatures[0] = hex"dead"; - signatures[1] = hex"beef"; - if (success || permissionRevertIndex != 0) { - policy.sudoSetValidSig(address(kernel), permissionId, hex"dead"); - } - if (success || permissionRevertIndex != 1) { - signer.sudoSetValidSig(address(kernel), permissionId, hex"beef"); - } - - return abi.encode(signatures); - } - - function _permissionSignHash(bytes32 hash, bool success) internal virtual returns (bytes memory sig) { - bytes[] memory signatures = new bytes[](2); - signatures[0] = hex"dead"; - signatures[1] = hex"beef"; - if (success || permissionRevertIndex != 0) { - policy.sudoSetPass(address(kernel), permissionId, true); - } - if (success || permissionRevertIndex != 1) { - signer.sudoSetPass(address(kernel), permissionId, true); - } - - return abi.encode(signatures); - } - - function enableSig( - uint256 nonce, - bool enableSuccess, - bool replayable, - Install[] memory packages, - function(bytes32, bool) internal returns(bytes memory) signEnable - ) internal returns (bytes memory sig) { - bytes32 digest = helper.installDigest(address(kernel), replayable, nonce, packages); - MockKernel mockKernel = new MockKernel(ep); - - if (!is7702) { - //vm.store(address(kernel), ERC1967_IMPLEMENTATION_SLOT, bytes32(uint256(uint160(address(mockKernel))))); - //assertEq(MockKernel(payable(address(kernel))).installDigest(replayable, nonce, packages), digest); - //vm.store(address(kernel), ERC1967_IMPLEMENTATION_SLOT, bytes32(uint256(uint160(address(factory.template()))))); - } - return signEnable(digest, enableSuccess); - } - - function encodeEnableValidatorSignature( - bytes4 selector, - uint256 nonce, - bool enableSuccess, - bool replayable, - function(bytes32, bool) internal returns(bytes memory) signEnable, - bytes memory userOpSig - ) internal returns (bytes memory sig) { - Install[] memory packages = new Install[](1); - packages[0] = Install({ - moduleType: 1, - module: address(newValidator), - moduleData: hex"", - internalData: abi.encodePacked(address(0), selector) - }); - sig = abi.encode( - uint256(0), packages, enableSig(nonce, enableSuccess, replayable, packages, signEnable), userOpSig - ); - } - - function encodeEnablePermissionSignature( - bytes4 selector, - uint256 nonce, - bool enableSuccess, - bool replayable, - function(bytes32, bool) internal returns(bytes memory) signEnable, - bytes memory userOpSig - ) internal returns (bytes memory sig) { - Install[] memory packages = new Install[](2); - packages[0] = Install({ - moduleType: 5, - module: address(policy), - moduleData: hex"", - internalData: abi.encodePacked(permissionId, address(0), selector) - }); - packages[1] = Install({ - moduleType: 6, - module: address(signer), - moduleData: hex"", - internalData: abi.encodePacked(permissionId) - }); - - sig = abi.encode( - uint256(0), packages, enableSig(nonce, enableSuccess, replayable, packages, signEnable), userOpSig - ); - } - - function encodeNonce(bool replayableUserOp, bool enableFlag, bool replayableEnable, bytes1 vType, bytes20 vId) - internal - returns (uint256 nonce) - { - uint8 uMode = 0; - if (replayableUserOp) { - uMode += 2 ** 6; - } - if (enableFlag) { - uMode += 2 ** 3; - } - if (replayableEnable) { - uMode += 2 ** 2; - } - ValidationMode vMode = ValidationMode.wrap(bytes1(uMode)); - uint192 key = uint192(bytes24(abi.encodePacked(uMode, vType, vId, bytes2(0x00)))); - return ep.getNonce(address(kernel), key); - } - function test_codesize() external { vm.skip(true); address implementation = address(factory.uups()); @@ -463,31 +252,10 @@ contract KernelTest is Test { signature: hex"" }); ops[0].signature = _validatorSignUserOp(ops[0], true, false); - //vm.expectRevert(abi.encodeWithSelector(IEntryPoint.FailedOp.selector, 0, "AA24 signature error")); vm.expectRevert(); ep.handleOps(ops, beneficiary); } - // function test_userop_validator_use_root_if_notinstalled() external entryPointTest { - // PackedUserOperation[] memory ops = new PackedUserOperation[](1); - // ops[0] = PackedUserOperation({ - // sender: address(kernel), - // nonce: encodeNonce(false, false, false, bytes1(0x01), bytes20(address(newValidator))), - // initCode: hex"", - // callData: abi.encodeWithSelector( - // Kernel.execute.selector, bytes32(0), abi.encodePacked(address(callee), uint256(0), MockCallee.foo.selector) - // ), - // accountGasLimits: bytes32(abi.encodePacked(uint128(1000000), uint128(1000000))), // TODO make this dynamic - // preVerificationGas: 1000000, - // gasFees: bytes32(abi.encodePacked(uint128(1), uint128(1))), - // paymasterAndData: hex"", - // signature: hex"" - // }); - // ops[0].signature = _rootSignUserOp(ops[0], true, false); - // ep.handleOps(ops, beneficiary); - // assertEq(callee.bar(), 1); - // } - function test_userop_validator_enable() external entryPointTest { PackedUserOperation[] memory ops = new PackedUserOperation[](1); ops[0] = PackedUserOperation({ @@ -576,26 +344,6 @@ contract KernelTest is Test { ep.handleOps(ops, beneficiary); } - // function test_userop_permission_use_root_if_notinstalled() external entryPointTest { - // PackedUserOperation[] memory ops = new PackedUserOperation[](1); - // ops[0] = PackedUserOperation({ - // sender: address(kernel), - // nonce: encodeNonce(false, false, false, bytes1(0x02), permissionId), - // initCode: hex"", - // callData: abi.encodeWithSelector( - // Kernel.execute.selector, bytes32(0), abi.encodePacked(address(callee), uint256(0), MockCallee.foo.selector) - // ), - // accountGasLimits: bytes32(abi.encodePacked(uint128(1000000), uint128(1000000))), // TODO make this dynamic - // preVerificationGas: 1000000, - // gasFees: bytes32(abi.encodePacked(uint128(1), uint128(1))), - // paymasterAndData: hex"", - // signature: hex"" - // }); - // ops[0].signature = _rootSignUserOp(ops[0], true, false); - // ep.handleOps(ops, beneficiary); - // assertEq(callee.bar(), 1); - // } - function test_userop_permission_enable() external entryPointTest { PackedUserOperation[] memory ops = new PackedUserOperation[](1); ops[0] = PackedUserOperation({ diff --git a/test/KernelTestBase.sol b/test/KernelTestBase.sol new file mode 100644 index 00000000..6f9de463 --- /dev/null +++ b/test/KernelTestBase.sol @@ -0,0 +1,219 @@ +pragma solidity ^0.8.0; + +import {Test} from "forge-std/Test.sol"; +import {EntryPointLib} from "./utils/EntryPointLib.sol"; +import {IEntryPoint} from "account-abstraction/interfaces/IEntryPoint.sol"; +import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; +import {Kernel} from "src/Kernel.sol"; +import {KernelUUPS} from "src/KernelUUPS.sol"; +import {KernelHelper} from "src/KernelHelper.sol"; +import {SelectorManager} from "src/core/SelectorManager.sol"; +import {KernelFactory} from "src/KernelFactory.sol"; +import {KernelUUPS} from "src/KernelUUPS.sol"; +import {KernelImmutableECDSA} from "src/KernelImmutableECDSA.sol"; +import {LibERC7579} from "solady/accounts/LibERC7579.sol"; +import {LibString} from "solady/utils/LibString.sol"; +import {Install} from "src/types/Structs.sol"; +import {MockFallback} from "./mock/MockFallback.sol"; +import {MockExecutor} from "./mock/MockExecutor.sol"; +import {MockValidator} from "./mock/MockValidator.sol"; +import {MockHook} from "./mock/MockHook.sol"; +import {MockPolicy} from "./mock/MockPolicy.sol"; +import {MockSigner} from "./mock/MockSigner.sol"; +import {MockERC721} from "./mock/MockERC721.sol"; +import {MockERC1155} from "./mock/MockERC1155.sol"; +import {MockCallee} from "./mock/MockCallee.sol"; +import {MockKernel} from "./mock/MockKernel.sol"; +import {IHook, IValidator} from "src/interfaces/IERC7579Modules.sol"; +import {CallType} from "src/types/Types.sol"; +import "src/types/Constants.sol"; +import "forge-std/console.sol"; +import "src/types/Error.sol"; +import "src/types/Events.sol"; +import "src/types/Structs.sol"; + +abstract contract KernelTestBase is Test { + IEntryPoint ep; + KernelFactory factory; + IValidator rootValidator; + bytes rootValidatorData; + MockValidator newValidator; + Kernel kernel; + MockCallee callee; + MockFallback mockFallback; + address executor; + address payable beneficiary; + MockPolicy policy; + MockSigner signer; + bytes20 permissionId; + uint256 permissionRevertIndex; + KernelHelper helper; + + bool is7702; + + modifier unitTest() { + vm.startPrank(address(ep)); + _; + vm.stopPrank(); + } + + modifier unitTestExecutor() { + vm.startPrank(address(executor)); + _; + vm.stopPrank(); + } + + modifier entryPointTest() { + _; + } + + function _initialize() internal virtual; + + function _rootSignUserOp(PackedUserOperation memory op, bool success, bool replay) + internal + virtual + returns (bytes memory sig) + { + MockValidator(address(rootValidator)).sudoSetSuccess(success); + return hex""; + } + + function _rootSignHash(bytes32 hash, bool success) internal virtual returns (bytes memory sig) { + if (success) { + MockValidator(address(rootValidator)).sudoSetValidSig(hex""); + } + return hex""; + } + + function _validatorSignUserOp(PackedUserOperation memory op, bool success, bool replay) + internal + virtual + returns (bytes memory sig) + { + newValidator.sudoSetSuccess(success); + return hex""; + } + + function _validatorSignHash(bytes32 hash, bool success) internal virtual returns (bytes memory sig) { + if (success) { + newValidator.sudoSetValidSig(hex""); + } + return hex""; + } + + function _permissionSignUserOp(PackedUserOperation memory op, bool success, bool replay) + internal + virtual + returns (bytes memory sig) + { + bytes[] memory signatures = new bytes[](2); + signatures[0] = hex"dead"; + signatures[1] = hex"beef"; + if (success || permissionRevertIndex != 0) { + policy.sudoSetValidSig(address(kernel), permissionId, hex"dead"); + } + if (success || permissionRevertIndex != 1) { + signer.sudoSetValidSig(address(kernel), permissionId, hex"beef"); + } + + return abi.encode(signatures); + } + + function _permissionSignHash(bytes32 hash, bool success) internal virtual returns (bytes memory sig) { + bytes[] memory signatures = new bytes[](2); + signatures[0] = hex"dead"; + signatures[1] = hex"beef"; + if (success || permissionRevertIndex != 0) { + policy.sudoSetPass(address(kernel), permissionId, true); + } + if (success || permissionRevertIndex != 1) { + signer.sudoSetPass(address(kernel), permissionId, true); + } + + return abi.encode(signatures); + } + + function enableSig( + uint256 nonce, + bool enableSuccess, + bool replayable, + Install[] memory packages, + function(bytes32, bool) internal returns(bytes memory) signEnable + ) internal returns (bytes memory sig) { + bytes32 digest = helper.installDigest(address(kernel), replayable, nonce, packages); + MockKernel mockKernel = new MockKernel(ep); + + if (!is7702) { + //vm.store(address(kernel), ERC1967_IMPLEMENTATION_SLOT, bytes32(uint256(uint160(address(mockKernel))))); + //assertEq(MockKernel(payable(address(kernel))).installDigest(replayable, nonce, packages), digest); + //vm.store(address(kernel), ERC1967_IMPLEMENTATION_SLOT, bytes32(uint256(uint160(address(factory.template()))))); + } + return signEnable(digest, enableSuccess); + } + + function encodeEnableValidatorSignature( + bytes4 selector, + uint256 nonce, + bool enableSuccess, + bool replayable, + function(bytes32, bool) internal returns(bytes memory) signEnable, + bytes memory userOpSig + ) internal returns (bytes memory sig) { + Install[] memory packages = new Install[](1); + packages[0] = Install({ + moduleType: 1, + module: address(newValidator), + moduleData: hex"", + internalData: abi.encodePacked(address(0), selector) + }); + sig = abi.encode( + uint256(0), packages, enableSig(nonce, enableSuccess, replayable, packages, signEnable), userOpSig + ); + } + + function encodeEnablePermissionSignature( + bytes4 selector, + uint256 nonce, + bool enableSuccess, + bool replayable, + function(bytes32, bool) internal returns(bytes memory) signEnable, + bytes memory userOpSig + ) internal returns (bytes memory sig) { + Install[] memory packages = new Install[](2); + packages[0] = Install({ + moduleType: 5, + module: address(policy), + moduleData: hex"", + internalData: abi.encodePacked(permissionId, address(0), selector) + }); + packages[1] = Install({ + moduleType: 6, + module: address(signer), + moduleData: hex"", + internalData: abi.encodePacked(permissionId) + }); + + sig = abi.encode( + uint256(0), packages, enableSig(nonce, enableSuccess, replayable, packages, signEnable), userOpSig + ); + } + + function encodeNonce(bool replayableUserOp, bool enableFlag, bool replayableEnable, bytes1 vType, bytes20 vId) + internal + returns (uint256 nonce) + { + uint8 uMode = 0; + if (replayableUserOp) { + uMode += 2 ** 6; + } + if (enableFlag) { + uMode += 2 ** 3; + } + if (replayableEnable) { + uMode += 2 ** 2; + } + ValidationMode vMode = ValidationMode.wrap(bytes1(uMode)); + uint192 key = uint192(bytes24(abi.encodePacked(uMode, vType, vId, bytes2(0x00)))); + return ep.getNonce(address(kernel), key); + } +} diff --git a/test/mock/MockCallee.sol b/test/mock/MockCallee.sol index edcc99e4..cbf01d81 100644 --- a/test/mock/MockCallee.sol +++ b/test/mock/MockCallee.sol @@ -1,22 +1,23 @@ pragma solidity ^0.8.0; contract MockCallee { - uint256 public value; + uint256 public bar; + string public data; - event MockEvent(address indexed caller, address indexed here); + event Lorem(); - function setValue(uint256 _value) public { - value = _value; + error Haha(); + + function foo() external { + bar++; + emit Lorem(); } - function addValue(uint256 _value) public { - value += _value; + function lorem() external { + data = "lorem ipsum"; } - function emitEvent(bool shouldFail) public { - if (shouldFail) { - revert("Hello"); - } - emit MockEvent(msg.sender, address(this)); + function forceRevert() external { + revert Haha(); } } diff --git a/test/mock/MockContractEth.sol b/test/mock/MockContractEth.sol new file mode 100644 index 00000000..eba33fac --- /dev/null +++ b/test/mock/MockContractEth.sol @@ -0,0 +1,11 @@ +pragma solidity ^0.8.0; + +contract MockContractETH { + function useTransfer(address payable recipient, uint256 v) external { + recipient.transfer(v); + } + + function useSend(address payable recipient, uint256 v) external { + require(recipient.send(v), "send failed"); + } +} From 3971eee5b04cce1de6475090e6c2c0e7c4915b2f Mon Sep 17 00:00:00 2001 From: leekt Date: Thu, 25 Sep 2025 10:46:30 +0900 Subject: [PATCH 055/121] kernel hook test --- test/Kernel.t.sol | 1164 +--------------------------------- test/KernelERC1271Test.sol | 259 ++++++++ test/KernelExecuteTest.sol | 144 +++++ test/KernelExecutorTest.sol | 139 ++++ test/KernelFactory.t.sol | 125 ++++ test/KernelHookTest.sol | 49 ++ test/KernelSelectorTest.sol | 153 +++++ test/KernelTestBase.sol | 81 +++ test/KernelUserOpTest.sol | 323 ++++++++++ test/KernelValidatorTest.sol | 193 ++++++ 10 files changed, 1483 insertions(+), 1147 deletions(-) create mode 100644 test/KernelERC1271Test.sol create mode 100644 test/KernelExecuteTest.sol create mode 100644 test/KernelExecutorTest.sol create mode 100644 test/KernelFactory.t.sol create mode 100644 test/KernelHookTest.sol create mode 100644 test/KernelSelectorTest.sol create mode 100644 test/KernelUserOpTest.sol create mode 100644 test/KernelValidatorTest.sol diff --git a/test/Kernel.t.sol b/test/Kernel.t.sol index 7f373293..6290254a 100644 --- a/test/Kernel.t.sol +++ b/test/Kernel.t.sol @@ -24,7 +24,6 @@ import {MockERC721} from "./mock/MockERC721.sol"; import {MockERC1155} from "./mock/MockERC1155.sol"; import {MockKernel} from "./mock/MockKernel.sol"; import {MockCallee} from "./mock/MockCallee.sol"; -import {MockContractETH} from "./mock/MockContractETH.sol"; import {IHook, IValidator} from "src/interfaces/IERC7579Modules.sol"; import {CallType} from "src/types/Types.sol"; import "src/types/Constants.sol"; @@ -33,8 +32,23 @@ import "src/types/Error.sol"; import "src/types/Events.sol"; import "src/types/Structs.sol"; import {KernelTestBase} from "./KernelTestBase.sol"; - -contract KernelTest is KernelTestBase { +import {KernelUserOpTest} from "./KernelUserOpTest.sol"; +import {KernelERC1271Test} from "./KernelERC1271Test.sol"; +import {KernelExecutorTest} from "./KernelExecutorTest.sol"; +import {KernelValidatorTest} from "./KernelValidatorTest.sol"; +import {KernelExecuteTest} from "./KernelExecuteTest.sol"; +import {KernelSelectorTest} from "./KernelSelectorTest.sol"; +import {KernelHookTest} from "./KernelHookTest.sol"; + +contract KernelTest is + KernelUserOpTest, + KernelERC1271Test, + KernelExecutorTest, + KernelValidatorTest, + KernelExecuteTest, + KernelSelectorTest, + KernelHookTest +{ function setUp() external { ep = EntryPointLib.deploy(); @@ -67,509 +81,6 @@ contract KernelTest is KernelTestBase { vm.stopPrank(); } - function test_codesize() external { - vm.skip(true); - address implementation = address(factory.uups()); - console.log("Code size :", implementation.code.length); - require(implementation.code.length <= 24576, "Code too big"); - console.log("space left :", 24576 - implementation.code.length); - } - - function test_receive_eth() external { - address sender = makeAddr("Sender"); - address payable k = payable(address(kernel)); - vm.deal(sender, 1e18); - // if not through kernel, only
call{value} works - vm.startPrank(sender); - vm.expectEmit(k); - emit Received(sender, uint256(1)); - (bool success,) = k.call{value: 1}(hex""); - require(success); - vm.stopPrank(); - - MockContractETH mock = new MockContractETH(); - vm.deal(address(mock), 1e18); - // if done through kernel, accepts both transfer and send - vm.startPrank(address(ep)); - vm.expectEmit(k); - emit Received(address(mock), uint256(1)); - kernel.execute( - bytes32(0), - abi.encodePacked( - address(mock), uint256(0), abi.encodeWithSelector(MockContractETH.useTransfer.selector, k, uint256(1)) - ) - ); - vm.expectEmit(k); - emit Received(address(mock), uint256(1)); - kernel.execute( - bytes32(0), - abi.encodePacked( - address(mock), uint256(0), abi.encodeWithSelector(MockContractETH.useSend.selector, k, uint256(1)) - ) - ); - vm.stopPrank(); - } - - function test_receive_erc721() external { - MockERC721 mock = new MockERC721(); - address sender = makeAddr("Sender"); - - mock.mint(sender, 1); - - vm.prank(sender); - mock.safeTransferFrom(sender, address(kernel), 1); - - mock.safeMint(address(kernel), 2); - } - - function test_receive_erc1155() external { - MockERC1155 mock = new MockERC1155(); - address sender = makeAddr("Sender"); - - mock.mint(sender, 1, 1, hex"deadbeef"); - vm.prank(sender); - mock.safeTransferFrom(sender, address(kernel), 1, 1, hex"deadbeef"); - - mock.mint(address(kernel), 1, 1, hex"deadbeef"); - - mock.mint(sender, 2, 4, hex"deadbeef"); - mock.mint(sender, 3, 5, hex"deadbeef"); - uint256[] memory ids = new uint256[](2); - ids[0] = 2; - ids[1] = 3; - - uint256[] memory amounts = new uint256[](2); - amounts[0] = 2; - amounts[1] = 3; - vm.prank(sender); - mock.safeBatchTransferFrom(sender, address(kernel), ids, amounts, hex"deadbeef"); - - mock.batchMint(address(kernel), ids, amounts, hex"deadbeef"); - } - - function test_executeuserop_root() external entryPointTest { - PackedUserOperation[] memory ops = new PackedUserOperation[](1); - ops[0] = PackedUserOperation({ - sender: address(kernel), - nonce: encodeNonce(false, false, false, bytes1(0), bytes20(0)), - initCode: hex"", - callData: abi.encodePacked( - Kernel.executeUserOp.selector, - abi.encodeWithSelector( - Kernel.execute.selector, - bytes32(0), - abi.encodePacked(address(callee), uint256(0), MockCallee.foo.selector) - ) - ), - accountGasLimits: bytes32(abi.encodePacked(uint128(1000000), uint128(1000000))), // TODO make this dynamic - preVerificationGas: 1000000, - gasFees: bytes32(abi.encodePacked(uint128(1), uint128(1))), - paymasterAndData: hex"", - signature: hex"" - }); - ops[0].signature = _rootSignUserOp(ops[0], true, false); - vm.startPrank(address(ep)); - kernel.executeUserOp(ops[0], keccak256("hello world")); - vm.stopPrank(); - assertEq(callee.bar(), 1); - } - - function test_userop_root() external entryPointTest { - PackedUserOperation[] memory ops = new PackedUserOperation[](1); - ops[0] = PackedUserOperation({ - sender: address(kernel), - nonce: encodeNonce(false, false, false, bytes1(0), bytes20(0)), - initCode: hex"", - callData: abi.encodeWithSelector( - Kernel.execute.selector, bytes32(0), abi.encodePacked(address(callee), uint256(0), MockCallee.foo.selector) - ), - accountGasLimits: bytes32(abi.encodePacked(uint128(1000000), uint128(1000000))), // TODO make this dynamic - preVerificationGas: 1000000, - gasFees: bytes32(abi.encodePacked(uint128(1), uint128(1))), - paymasterAndData: hex"", - signature: hex"" - }); - ops[0].signature = _rootSignUserOp(ops[0], true, false); - vm.startSnapshotGas("Root - foo()"); - ep.handleOps(ops, beneficiary); - vm.stopSnapshotGas(); - assertEq(callee.bar(), 1); - } - - function test_userop_root_replayable() external entryPointTest { - PackedUserOperation[] memory ops = new PackedUserOperation[](1); - ops[0] = PackedUserOperation({ - sender: address(kernel), - nonce: encodeNonce(true, false, false, bytes1(0), bytes20(0)), - initCode: hex"", - callData: abi.encodeWithSelector( - Kernel.execute.selector, bytes32(0), abi.encodePacked(address(callee), uint256(0), MockCallee.foo.selector) - ), - accountGasLimits: bytes32(abi.encodePacked(uint128(1000000), uint128(1000000))), // TODO make this dynamic - preVerificationGas: 1000000, - gasFees: bytes32(abi.encodePacked(uint128(1), uint128(1))), - paymasterAndData: hex"", - signature: hex"" - }); - ops[0].signature = _rootSignUserOp(ops[0], true, true); - ep.handleOps(ops, beneficiary); - assertEq(callee.bar(), 1); - } - - function test_userop_root_aa24_validation_failed() external entryPointTest { - PackedUserOperation[] memory ops = new PackedUserOperation[](1); - ops[0] = PackedUserOperation({ - sender: address(kernel), - nonce: encodeNonce(false, false, false, bytes1(0x00), bytes20(0)), - initCode: hex"", - callData: abi.encodeWithSelector( - Kernel.execute.selector, bytes32(0), abi.encodePacked(address(callee), uint256(0), MockCallee.foo.selector) - ), - accountGasLimits: bytes32(abi.encodePacked(uint128(1000000), uint128(1000000))), // TODO make this dynamic - preVerificationGas: 1000000, - gasFees: bytes32(abi.encodePacked(uint128(1), uint128(1))), - paymasterAndData: hex"", - signature: hex"" - }); - ops[0].signature = _rootSignUserOp(ops[0], false, false); - vm.expectRevert(abi.encodeWithSelector(IEntryPoint.FailedOp.selector, 0, "AA24 signature error")); - ep.handleOps(ops, beneficiary); - } - - function test_userop_validator_aa24_notinstalled() external entryPointTest { - PackedUserOperation[] memory ops = new PackedUserOperation[](1); - ops[0] = PackedUserOperation({ - sender: address(kernel), - nonce: encodeNonce(false, false, false, bytes1(0x01), bytes20(address(newValidator))), - initCode: hex"", - callData: abi.encodeWithSelector( - Kernel.execute.selector, bytes32(0), abi.encodePacked(address(callee), uint256(0), MockCallee.foo.selector) - ), - accountGasLimits: bytes32(abi.encodePacked(uint128(1000000), uint128(1000000))), // TODO make this dynamic - preVerificationGas: 1000000, - gasFees: bytes32(abi.encodePacked(uint128(1), uint128(1))), - paymasterAndData: hex"", - signature: hex"" - }); - ops[0].signature = _validatorSignUserOp(ops[0], true, false); - vm.expectRevert(); - ep.handleOps(ops, beneficiary); - } - - function test_userop_validator_enable() external entryPointTest { - PackedUserOperation[] memory ops = new PackedUserOperation[](1); - ops[0] = PackedUserOperation({ - sender: address(kernel), - nonce: encodeNonce(false, true, false, bytes1(0x01), bytes20(address(newValidator))), - initCode: hex"", - callData: abi.encodeWithSelector( - Kernel.execute.selector, bytes32(0), abi.encodePacked(address(callee), uint256(0), MockCallee.foo.selector) - ), - accountGasLimits: bytes32(abi.encodePacked(uint128(1000000), uint128(1000000))), // TODO make this dynamic - preVerificationGas: 1000000, - gasFees: bytes32(abi.encodePacked(uint128(1), uint128(1))), - paymasterAndData: hex"", - signature: hex"" - }); - ops[0].signature = encodeEnableValidatorSignature( - Kernel.execute.selector, 0, true, false, _rootSignHash, _validatorSignUserOp(ops[0], true, false) - ); - ep.handleOps(ops, beneficiary); - assertEq(callee.bar(), 1); - } - - function test_userop_validator_aa24_enable_fail_wrong_signature() external entryPointTest { - PackedUserOperation[] memory ops = new PackedUserOperation[](1); - ops[0] = PackedUserOperation({ - sender: address(kernel), - nonce: encodeNonce(false, true, false, bytes1(0x01), bytes20(address(newValidator))), - initCode: hex"", - callData: abi.encodeWithSelector( - Kernel.execute.selector, bytes32(0), abi.encodePacked(address(callee), uint256(0), MockCallee.foo.selector) - ), - accountGasLimits: bytes32(abi.encodePacked(uint128(1000000), uint128(1000000))), // TODO make this dynamic - preVerificationGas: 1000000, - gasFees: bytes32(abi.encodePacked(uint128(1), uint128(1))), - paymasterAndData: hex"", - signature: hex"" - }); - ops[0].signature = encodeEnableValidatorSignature( - Kernel.execute.selector, 0, false, false, _rootSignHash, _validatorSignUserOp(ops[0], true, false) - ); - vm.expectRevert(abi.encodeWithSelector(IEntryPoint.FailedOp.selector, 0, "AA24 signature error")); - ep.handleOps(ops, beneficiary); - } - - function test_userop_validator_aa24_validation_failed() external entryPointTest { - PackedUserOperation[] memory ops = new PackedUserOperation[](1); - ops[0] = PackedUserOperation({ - sender: address(kernel), - nonce: encodeNonce(false, true, false, bytes1(0x01), bytes20(address(newValidator))), - initCode: hex"", - callData: abi.encodeWithSelector( - Kernel.execute.selector, bytes32(0), abi.encodePacked(address(callee), uint256(0), MockCallee.foo.selector) - ), - accountGasLimits: bytes32(abi.encodePacked(uint128(1000000), uint128(1000000))), // TODO make this dynamic - preVerificationGas: 1000000, - gasFees: bytes32(abi.encodePacked(uint128(1), uint128(1))), - paymasterAndData: hex"", - signature: hex"" - }); - - ops[0].signature = encodeEnableValidatorSignature( - Kernel.execute.selector, 0, true, false, _rootSignHash, _validatorSignUserOp(ops[0], false, false) - ); - vm.expectRevert(abi.encodeWithSelector(IEntryPoint.FailedOp.selector, 0, "AA24 signature error")); - ep.handleOps(ops, beneficiary); - } - - function test_userop_permission_aa24_notinstalled() external entryPointTest { - PackedUserOperation[] memory ops = new PackedUserOperation[](1); - ops[0] = PackedUserOperation({ - sender: address(kernel), - nonce: encodeNonce(false, false, false, bytes1(0x02), permissionId), - initCode: hex"", - callData: abi.encodeWithSelector( - Kernel.execute.selector, bytes32(0), abi.encodePacked(address(callee), uint256(0), MockCallee.foo.selector) - ), - accountGasLimits: bytes32(abi.encodePacked(uint128(1000000), uint128(1000000))), // TODO make this dynamic - preVerificationGas: 1000000, - gasFees: bytes32(abi.encodePacked(uint128(1), uint128(1))), - paymasterAndData: hex"", - signature: hex"" - }); - ops[0].signature = _permissionSignUserOp(ops[0], true, false); - //vm.expectRevert(abi.encodeWithSelector(IEntryPoint.FailedOp.selector, 0, "AA24 signature error")); - vm.expectRevert(); - ep.handleOps(ops, beneficiary); - } - - function test_userop_permission_enable() external entryPointTest { - PackedUserOperation[] memory ops = new PackedUserOperation[](1); - ops[0] = PackedUserOperation({ - sender: address(kernel), - nonce: encodeNonce(false, true, false, bytes1(0x02), permissionId), - initCode: hex"", - callData: abi.encodeWithSelector( - Kernel.execute.selector, bytes32(0), abi.encodePacked(address(callee), uint256(0), MockCallee.foo.selector) - ), - accountGasLimits: bytes32(abi.encodePacked(uint128(1000000), uint128(1000000))), // TODO make this dynamic - preVerificationGas: 1000000, - gasFees: bytes32(abi.encodePacked(uint128(1), uint128(1))), - paymasterAndData: hex"", - signature: hex"" - }); - - ops[0].signature = encodeEnablePermissionSignature( - Kernel.execute.selector, 0, true, false, _rootSignHash, _permissionSignUserOp(ops[0], true, false) - ); - ep.handleOps(ops, beneficiary); - assertEq(callee.bar(), 1); - } - - function test_userop_permission_aa24_enable_fail_wrong_signature() external entryPointTest { - PackedUserOperation[] memory ops = new PackedUserOperation[](1); - ops[0] = PackedUserOperation({ - sender: address(kernel), - nonce: encodeNonce(false, true, false, bytes1(0x02), permissionId), - initCode: hex"", - callData: abi.encodeWithSelector( - Kernel.execute.selector, bytes32(0), abi.encodePacked(address(callee), uint256(0), MockCallee.foo.selector) - ), - accountGasLimits: bytes32(abi.encodePacked(uint128(1000000), uint128(1000000))), // TODO make this dynamic - preVerificationGas: 1000000, - gasFees: bytes32(abi.encodePacked(uint128(1), uint128(1))), - paymasterAndData: hex"", - signature: hex"" - }); - ops[0].signature = encodeEnablePermissionSignature( - Kernel.execute.selector, 0, false, false, _rootSignHash, _permissionSignUserOp(ops[0], true, false) - ); - vm.expectRevert(abi.encodeWithSelector(IEntryPoint.FailedOp.selector, 0, "AA24 signature error")); - ep.handleOps(ops, beneficiary); - } - - function test_userop_permission_aa24_policy_failed() external entryPointTest { - PackedUserOperation[] memory ops = new PackedUserOperation[](1); - ops[0] = PackedUserOperation({ - sender: address(kernel), - nonce: encodeNonce(false, true, false, bytes1(0x02), permissionId), - initCode: hex"", - callData: abi.encodeWithSelector( - Kernel.execute.selector, bytes32(0), abi.encodePacked(address(callee), uint256(0), MockCallee.foo.selector) - ), - accountGasLimits: bytes32(abi.encodePacked(uint128(1000000), uint128(1000000))), // TODO make this dynamic - preVerificationGas: 1000000, - gasFees: bytes32(abi.encodePacked(uint128(1), uint128(1))), - paymasterAndData: hex"", - signature: hex"" - }); - ops[0].signature = encodeEnablePermissionSignature( - Kernel.execute.selector, 0, true, false, _rootSignHash, _permissionSignUserOp(ops[0], false, false) - ); - vm.expectRevert(abi.encodeWithSelector(IEntryPoint.FailedOp.selector, 0, "AA24 signature error")); - ep.handleOps(ops, beneficiary); - } - - function test_userop_permission_aa24_signer_validation_failed() external entryPointTest { - PackedUserOperation[] memory ops = new PackedUserOperation[](1); - ops[0] = PackedUserOperation({ - sender: address(kernel), - nonce: encodeNonce(false, true, false, bytes1(0x02), permissionId), - initCode: hex"", - callData: abi.encodeWithSelector( - Kernel.execute.selector, bytes32(0), abi.encodePacked(address(callee), uint256(0), MockCallee.foo.selector) - ), - accountGasLimits: bytes32(abi.encodePacked(uint128(1000000), uint128(1000000))), // TODO make this dynamic - preVerificationGas: 1000000, - gasFees: bytes32(abi.encodePacked(uint128(1), uint128(1))), - paymasterAndData: hex"", - signature: hex"" - }); - permissionRevertIndex = 1; - ops[0].signature = encodeEnablePermissionSignature( - Kernel.execute.selector, 0, true, false, _rootSignHash, _permissionSignUserOp(ops[0], false, false) - ); - vm.expectRevert(abi.encodeWithSelector(IEntryPoint.FailedOp.selector, 0, "AA24 signature error")); - ep.handleOps(ops, beneficiary); - } - - function test_deploy_root_validator() external unitTest { - vm.skip(is7702); - Install[] memory pkgs = new Install[](1); - pkgs[0] = - Install({moduleType: 1, module: address(rootValidator), moduleData: rootValidatorData, internalData: hex""}); - vm.startSnapshotGas("Mock - deploy()"); - Kernel k = factory.deploy(pkgs, 1); - vm.stopSnapshotGas(); - } - - function test_deploy_root_permission() external unitTest { - Install[] memory pkgs = new Install[](2); - pkgs[0] = Install({ - moduleType: 5, - module: address(policy), - internalData: abi.encodePacked(permissionId), - moduleData: hex"" - }); - pkgs[1] = Install({moduleType: 1, module: address(newValidator), internalData: hex"", moduleData: hex""}); - Kernel k = factory.deploy(pkgs, 1); - assertEq(k.accountId(), "kernel.v0.4"); - assertEq(k.registry(), address(0)); - } - - function test_deploy_root_fail_invalid_root() external unitTest { - Install[] memory pkgs = new Install[](2); - pkgs[0] = Install({moduleType: 2, module: address(executor), internalData: hex"", moduleData: hex""}); - pkgs[1] = Install({moduleType: 1, module: address(newValidator), internalData: hex"", moduleData: hex""}); - vm.expectRevert(InvalidRootValidation.selector); - Kernel k = factory.deploy(pkgs, 1); - } - - function test_deploy_existing() external { - vm.skip(is7702); - Install[] memory pkgs = new Install[](1); - pkgs[0] = - Install({moduleType: 1, module: address(rootValidator), moduleData: rootValidatorData, internalData: hex""}); - Kernel k = factory.deploy(pkgs, 1); - assertEq(address(k), address(factory.deploy(pkgs, 1))); - } - - function test_deploy_with_call() external unitTest { - vm.skip(is7702); - Install[] memory initPkgs = new Install[](1); - initPkgs[0] = - Install({moduleType: 1, module: address(rootValidator), moduleData: rootValidatorData, internalData: hex""}); - Install[] memory pkgs = new Install[](1); - pkgs[0] = Install({moduleType: 1, module: address(newValidator), moduleData: hex"", internalData: hex""}); - kernel = Kernel(payable(factory.getAddress(initPkgs, 1))); - bytes memory sig = enableSig(0, true, false, pkgs, _rootSignHash); - Kernel k = factory.deployWithCall(initPkgs, 1, abi.encodeWithSelector(0xa706cd33, false, 0, pkgs, sig)); - assertEq(address(k), address(kernel)); - ValidationInfo memory vInfo = k.validationInfo(ValidationId.wrap(bytes20(address(newValidator)))); - assertTrue(vInfo.vType == VALIDATION_TYPE_VALIDATOR); - } - - function test_install_executor_oninstall_success() external unitTest { - assertTrue(kernel.supportsModule(2)); - address newEx = address(new MockExecutor()); - kernel.installModule(2, newEx, abi.encode(hex"deadbeef", "")); - assertEq(address(kernel.executorConfig(newEx).hook), address(1)); - assertTrue(kernel.isModuleInstalled(2, newEx, hex"")); - } - - function test_install_executor_oninstall_fail() external unitTest { - address newEx = makeAddr("New Executor"); - kernel.installModule(2, newEx, abi.encode(hex"", "")); - assertEq(address(kernel.executorConfig(newEx).hook), address(1)); - assertTrue(kernel.isModuleInstalled(2, newEx, hex"")); - } - - function test_uninstall_executor_onuninstall_success() external unitTest { - address newEx = address(new MockExecutor()); - kernel.installModule(2, newEx, abi.encode(hex"deadbeef", "")); - assertEq(address(kernel.executorConfig(newEx).hook), address(1)); - kernel.uninstallModule(2, newEx, abi.encode(hex"", hex"")); - assertEq(address(kernel.executorConfig(newEx).hook), address(0)); - } - - function test_uninstall_executor_onuninstall_fail() external unitTest { - address newEx = makeAddr("New Executor"); - kernel.installModule(2, newEx, abi.encode(hex"", "")); - assertEq(address(kernel.executorConfig(newEx).hook), address(1)); - kernel.uninstallModule(2, newEx, abi.encode(hex"", hex"")); - assertEq(address(kernel.executorConfig(newEx).hook), address(0)); - } - - function test_set_valid_nonce() external unitTest { - kernel.setValidNonceFrom(1); - assertEq(kernel.validNonceFrom(), 1); - - Install[] memory packages = new Install[](2); - packages[0] = Install({moduleType: 1, module: address(newValidator), internalData: hex"", moduleData: hex""}); - packages[1] = Install({ - moduleType: 5, - module: address(policy), - internalData: abi.encodePacked(permissionId), - moduleData: hex"" - }); - bytes memory sig = enableSig(0, true, false, packages, _rootSignHash); - vm.expectRevert(InvalidNonce.selector); - kernel.installModule(false, 0, packages, sig); - sig = enableSig(uint256(1) << 64, true, false, packages, _rootSignHash); - vm.expectRevert(InvalidNonce.selector); - kernel.installModule(false, uint256(1) << 64, packages, sig); - sig = enableSig(1, true, false, packages, _rootSignHash); - kernel.installModule(false, 1, packages, sig); - } - - function test_set_nonce() external unitTest { - kernel.setNonce(0, 1); - assertEq(kernel.nonce(0), 1); - - Install[] memory packages = new Install[](2); - packages[0] = Install({moduleType: 1, module: address(newValidator), internalData: hex"", moduleData: hex""}); - packages[1] = Install({ - moduleType: 5, - module: address(policy), - internalData: abi.encodePacked(permissionId), - moduleData: hex"" - }); - bytes memory sig = enableSig(0, true, false, packages, _rootSignHash); - vm.expectRevert(InvalidNonce.selector); - kernel.installModule(false, 0, packages, sig); - sig = enableSig(uint256(1) << 64, true, false, packages, _rootSignHash); - kernel.installModule(false, uint256(1) << 64, packages, sig); - } - - function test_set_valid_nonce_decrease_nonce() external unitTest { - kernel.setValidNonceFrom(100); - assertEq(kernel.validNonceFrom(), 100); - assertEq(kernel.nonce(0), 100); - vm.expectRevert(InvalidNonce.selector); - kernel.setValidNonceFrom(1); - } - function test_install_packages_with_signature() external unitTest { Install[] memory packages = new Install[](2); packages[0] = Install({moduleType: 1, module: address(newValidator), internalData: hex"", moduleData: hex""}); @@ -594,20 +105,6 @@ contract KernelTest is KernelTestBase { kernel.installModule(true, 0, packages, enableSig(0, true, true, packages, _rootSignHash)); } - function test_change_root() external unitTest { - Install[] memory packages = new Install[](2); - packages[0] = Install({moduleType: 1, module: address(newValidator), internalData: hex"", moduleData: hex""}); - packages[1] = Install({ - moduleType: 5, - module: address(policy), - internalData: abi.encodePacked(permissionId), - moduleData: hex"" - }); - kernel.installModule(false, 0, packages, enableSig(0, true, false, packages, _rootSignHash)); - - kernel.setRoot(ValidationId.wrap(bytes20(address(newValidator)))); - } - function test_upgradeTo() external unitTest { vm.skip(is7702); KernelUUPS newTemplate = new KernelUUPS(ep); @@ -616,134 +113,6 @@ contract KernelTest is KernelTestBase { assertEq(address(uint160(uint256(impl))), address(newTemplate)); } - function test_erc7739() public { - assertEq( - kernel.isValidSignature(0x7739773977397739773977397739773977397739773977397739773977397739, ""), - bytes4(0x77390001) - ); - } - - function test_erc1271_root() external unitTest { - bytes32 messageHash = keccak256("Hello world"); - (bytes32 contentsHash, bytes memory sig) = - _erc1271Signature(messageHash, "C(bytes32 stuff)", "", _rootSignHash, false, true); - bytes4 ret = kernel.isValidSignature(_toContentsHash(contentsHash), abi.encodePacked(bytes20(0), sig)); - assertEq(ret, ERC1271_MAGICVALUE); - } - - function test_erc1271_fail_invalid() external unitTest { - bytes32 messageHash = keccak256("Hello world"); - (bytes32 contentsHash, bytes memory sig) = - _erc1271Signature(messageHash, "C(bytes32 stuff)", "", _rootSignHash, false, true); - bytes4 ret = - kernel.isValidSignature(_toContentsHash(contentsHash), abi.encodePacked(bytes20(address(this)), sig)); - assertEq(ret, ERC1271_INVALID); - } - - function test_erc1271_root_fail() external unitTest { - bytes32 messageHash = keccak256("Hello world"); - (bytes32 contentsHash, bytes memory sig) = - _erc1271Signature(messageHash, "C(bytes32 stuff)", "", _rootSignHash, false, false); - bytes4 ret = kernel.isValidSignature(_toContentsHash(contentsHash), abi.encodePacked(bytes20(0), sig)); - assertEq(ret, ERC1271_INVALID); - } - - function test_erc1271_root_personal_sign() external unitTest { - bytes32 messageHash = keccak256("Hello world"); - bytes32 personalHash = _toERC1271HashPersonalSign(messageHash); - bytes memory sig = _rootSignHash(personalHash, true); - bytes4 ret = kernel.isValidSignature(messageHash, abi.encodePacked(bytes20(0), sig)); - assertEq(ret, ERC1271_MAGICVALUE); - } - - function test_erc1271_root_personal_sign_fail() external unitTest { - bytes32 messageHash = keccak256("Hello world"); - bytes32 personalHash = _toERC1271HashPersonalSign(messageHash); - bytes memory sig = _rootSignHash(personalHash, false); - bytes4 ret = kernel.isValidSignature(messageHash, abi.encodePacked(bytes20(0), sig)); - assertEq(ret, ERC1271_INVALID); - } - - function test_erc1271_validator() external unitTest { - bytes32 messageHash = keccak256("Hello world"); - (bytes32 contentsHash, bytes memory sig) = - _erc1271Signature(messageHash, "C(bytes32 stuff)", "", _validatorSignHash, false, true); - kernel.installModule(1, address(newValidator), abi.encode(hex"", hex"")); - bytes4 ret = kernel.isValidSignature( - _toContentsHash(contentsHash), abi.encodePacked(bytes20(address(newValidator)), sig) - ); - assertEq(ret, ERC1271_MAGICVALUE); - } - - function test_erc1271_validator_fail() external unitTest { - bytes32 messageHash = keccak256("Hello world"); - (bytes32 contentsHash, bytes memory sig) = - _erc1271Signature(messageHash, "C(bytes32 stuff)", "", _validatorSignHash, false, false); - kernel.installModule(1, address(newValidator), abi.encode(hex"", hex"")); - bytes4 ret = kernel.isValidSignature( - _toContentsHash(contentsHash), abi.encodePacked(bytes20(address(newValidator)), sig) - ); - assertEq(ret, ERC1271_INVALID); - } - - function test_erc1271_validator_personal_sign() external unitTest { - bytes32 messageHash = keccak256("Hello world"); - bytes32 personalHash = _toERC1271HashPersonalSign(messageHash); - bytes memory sig = _validatorSignHash(personalHash, true); - kernel.installModule(1, address(newValidator), abi.encode(hex"", hex"")); - bytes4 ret = kernel.isValidSignature(messageHash, abi.encodePacked(bytes20(address(newValidator)), sig)); - assertEq(ret, ERC1271_MAGICVALUE); - } - - function test_erc1271_validator_personal_sign_fail() external unitTest { - bytes32 messageHash = keccak256("Hello world"); - bytes32 personalHash = _toERC1271HashPersonalSign(messageHash); - bytes memory sig = _validatorSignHash(personalHash, false); - kernel.installModule(1, address(newValidator), abi.encode(hex"", hex"")); - bytes4 ret = kernel.isValidSignature(messageHash, abi.encodePacked(bytes20(address(newValidator)), sig)); - assertEq(ret, ERC1271_INVALID); - } - - function test_erc1271_permission() external unitTest { - bytes32 messageHash = keccak256("Hello world"); - (bytes32 contentsHash, bytes memory sig) = - _erc1271Signature(messageHash, "C(bytes32 stuff)", "", _permissionSignHash, false, true); - kernel.installModule(5, address(policy), abi.encode(hex"deadbeef", abi.encodePacked(permissionId))); - kernel.installModule(6, address(signer), abi.encode(hex"deadbeef", abi.encodePacked(permissionId))); - bytes4 ret = kernel.isValidSignature(_toContentsHash(contentsHash), abi.encodePacked(permissionId, sig)); - assertEq(ret, ERC1271_MAGICVALUE); - } - - function test_erc1271_permission_fail() external unitTest { - bytes32 messageHash = keccak256("Hello world"); - (bytes32 contentsHash, bytes memory sig) = - _erc1271Signature(messageHash, "C(bytes32 stuff)", "", _permissionSignHash, false, false); - kernel.installModule(5, address(policy), abi.encode(hex"deadbeef", abi.encodePacked(permissionId))); - kernel.installModule(6, address(signer), abi.encode(hex"deadbeef", abi.encodePacked(permissionId))); - bytes4 ret = kernel.isValidSignature(_toContentsHash(contentsHash), abi.encodePacked(permissionId, sig)); - assertEq(ret, ERC1271_INVALID); - } - - function test_erc1271_permission_personal_sign() external unitTest { - bytes32 messageHash = keccak256("Hello world"); - bytes32 personalHash = _toERC1271HashPersonalSign(messageHash); - bytes memory sig = _permissionSignHash(personalHash, true); - kernel.installModule(5, address(policy), abi.encode(hex"deadbeef", abi.encodePacked(permissionId))); - kernel.installModule(6, address(signer), abi.encode(hex"deadbeef", abi.encodePacked(permissionId))); - bytes4 ret = kernel.isValidSignature(messageHash, abi.encodePacked(permissionId, sig)); - assertEq(ret, ERC1271_MAGICVALUE); - } - - function test_erc1271_permission_personal_sign_fail() external unitTest { - bytes32 messageHash = keccak256("Hello world"); - bytes32 personalHash = _toERC1271HashPersonalSign(messageHash); - bytes memory sig = _permissionSignHash(personalHash, false); - kernel.installModule(5, address(policy), abi.encode(hex"deadbeef", abi.encodePacked(permissionId))); - kernel.installModule(6, address(signer), abi.encode(hex"deadbeef", abi.encodePacked(permissionId))); - bytes4 ret = kernel.isValidSignature(messageHash, abi.encodePacked(permissionId, sig)); - assertEq(ret, ERC1271_INVALID); - } - function test_install_invalid() external unitTest { MockHook mockHook = new MockHook(); vm.expectRevert(NotImplemented.selector); @@ -757,503 +126,4 @@ contract KernelTest is KernelTestBase { vm.expectRevert(NotImplemented.selector); kernel.uninstallModule(10, address(mockHook), abi.encode(hex"", "")); } - - function test_install_hook() external unitTest { - assertTrue(kernel.supportsModule(4)); - MockHook mockHook = new MockHook(); - kernel.installModule(4, address(mockHook), abi.encode(hex"", "")); - assertTrue(kernel.isModuleInstalled(4, address(mockHook), hex"")); - } - - function test_uninstall_hook() external unitTest { - MockHook mockHook = new MockHook(); - kernel.installModule(4, address(mockHook), abi.encode(hex"", "")); - kernel.uninstallModule(4, address(mockHook), abi.encode(hex"", "")); - } - - function test_install_validator() external unitTest { - assertTrue(kernel.supportsModule(1)); - ValidationId vId = ValidationId.wrap(bytes20(address(newValidator))); - kernel.installModule(1, address(newValidator), abi.encode(hex"deadbeef", hex"")); - ValidationInfo memory vInfo = kernel.validationInfo(vId); - assertTrue(vInfo.vType == VALIDATION_TYPE_VALIDATOR); - bytes4 ret = kernel.isValidSignature( - keccak256("Hello world"), abi.encodePacked(newValidator, _validatorSignHash(keccak256("Hello world"), true)) - ); - assertEq(ret, ERC1271_MAGICVALUE); - assertTrue(kernel.isModuleInstalled(1, address(newValidator), hex"")); - } - - function test_uninstall_validator() external unitTest { - ValidationId vId = ValidationId.wrap(bytes20(address(newValidator))); - kernel.installModule(1, address(newValidator), abi.encode(hex"deadbeef", hex"")); - ValidationInfo memory vInfo = kernel.validationInfo(vId); - assertTrue(vInfo.vType == VALIDATION_TYPE_VALIDATOR); - kernel.uninstallModule(1, address(newValidator), abi.encode(hex"deadbeef", hex"")); - vInfo = kernel.validationInfo(vId); - assertTrue(vInfo.vType == VALIDATION_TYPE_ROOT); - } - - function test_install_permission() external unitTest { - assertTrue(kernel.supportsModule(5)); - assertTrue(kernel.supportsModule(6)); - ValidationId vId = ValidationId.wrap(permissionId); - ValidationInfo memory vInfo = kernel.validationInfo(vId); - assertTrue(vInfo.vType == VALIDATION_TYPE_ROOT); - assertFalse(kernel.isModuleInstalled(5, address(policy), abi.encodePacked(permissionId))); - assertFalse(kernel.isModuleInstalled(6, address(signer), abi.encodePacked(permissionId))); - kernel.installModule(5, address(policy), abi.encode(hex"deadbeef", abi.encodePacked(permissionId))); - kernel.installModule(6, address(signer), abi.encode(hex"deadbeef", abi.encodePacked(permissionId))); - bytes4 ret = kernel.isValidSignature( - keccak256("Hello world"), - abi.encodePacked(permissionId, _permissionSignHash(keccak256("Hello world"), true)) - ); - assertEq(ret, ERC1271_MAGICVALUE); - assertTrue(kernel.isModuleInstalled(5, address(policy), abi.encodePacked(permissionId))); - assertTrue(kernel.isModuleInstalled(6, address(signer), abi.encodePacked(permissionId))); - } - - function test_install_policy() external unitTest { - assertTrue(kernel.supportsModule(5)); - MockPolicy mock = new MockPolicy(); - ValidationId vId = ValidationId.wrap(permissionId); - ValidationInfo memory vInfo = kernel.validationInfo(vId); - assertTrue(vInfo.vType == VALIDATION_TYPE_ROOT); - kernel.installModule(5, address(mock), abi.encode(hex"deadbeef", abi.encodePacked(vId))); - vInfo = kernel.validationInfo(vId); - assertTrue(vInfo.vType == VALIDATION_TYPE_PERMISSION); - assertTrue(kernel.isModuleInstalled(5, address(mock), abi.encodePacked(permissionId))); - } - - function test_uninstall_policy() external unitTest { - MockPolicy mock = new MockPolicy(); - ValidationId vId = ValidationId.wrap(permissionId); - ValidationInfo memory vInfo = kernel.validationInfo(vId); - assertTrue(vInfo.vType == VALIDATION_TYPE_ROOT); - kernel.installModule(5, address(mock), abi.encode(hex"deadbeef", abi.encodePacked(vId))); - vInfo = kernel.validationInfo(vId); - assertTrue(vInfo.vType == VALIDATION_TYPE_PERMISSION); - kernel.uninstallModule(5, address(mock), abi.encode(hex"deadbeef", abi.encodePacked(vId))); - vInfo = kernel.validationInfo(vId); - assertTrue(vInfo.vType == VALIDATION_TYPE_ROOT); - } - - function test_install_signer() external unitTest { - assertTrue(kernel.supportsModule(6)); - MockSigner mock = new MockSigner(); - ValidationId vId = ValidationId.wrap(permissionId); - ValidationInfo memory vInfo = kernel.validationInfo(vId); - assertTrue(vInfo.vType == VALIDATION_TYPE_ROOT); - kernel.installModule(6, address(mock), abi.encode(hex"deadbeef", abi.encodePacked(vId))); - vInfo = kernel.validationInfo(vId); - assertTrue(vInfo.vType == VALIDATION_TYPE_PERMISSION); - assertTrue(kernel.isModuleInstalled(6, address(mock), abi.encodePacked(permissionId))); - } - - function test_uninstall_signer() external unitTest { - MockSigner mock = new MockSigner(); - ValidationId vId = ValidationId.wrap(bytes20(keccak256(abi.encodePacked("deadbeef")))); - ValidationInfo memory vInfo = kernel.validationInfo(vId); - assertTrue(vInfo.vType == VALIDATION_TYPE_ROOT); - kernel.installModule(6, address(mock), abi.encode(hex"deadbeef", abi.encodePacked(vId))); - vInfo = kernel.validationInfo(vId); - assertTrue(vInfo.vType == VALIDATION_TYPE_PERMISSION); - assertTrue(vInfo.signer == address(mock)); - kernel.uninstallModule(6, address(mock), abi.encode(hex"deadbeef", abi.encodePacked(vId))); - vInfo = kernel.validationInfo(vId); - assertTrue(vInfo.vType == VALIDATION_TYPE_ROOT); - assertTrue(vInfo.signer == address(0)); - } - - function test_install_selector_call() external unitTest { - assertTrue(kernel.supportsModule(3)); - kernel.installModule( - 3, - address(mockFallback), - abi.encode( - hex"deadbeef", abi.encodePacked(MockFallback.fallbackFunction.selector, bytes1(0x00), address(1)) - ) - ); - vm.expectEmit(address(mockFallback)); - emit MockFallback.Foobar(); - uint256 res = MockFallback(address(kernel)).fallbackFunction(10); - assertEq(res, 100); - SelectorManager.SelectorConfig memory c = kernel.selectorConfig(MockFallback.fallbackFunction.selector); - assertEq(address(c.target), address(mockFallback)); - assertEq(address(c.hook), address(1)); - assertTrue(c.callType == CallType.wrap(bytes1(0x00))); - assertTrue( - kernel.isModuleInstalled(3, address(mockFallback), abi.encodePacked(MockFallback.fallbackFunction.selector)) - ); - } - - function test_install_selector_call_withhook() external unitTest { - MockHook mockHook = new MockHook(); - kernel.installModule(4, address(mockHook), abi.encode(hex"", "")); - kernel.installModule( - 3, - address(mockFallback), - abi.encode( - hex"deadbeef", abi.encodePacked(MockFallback.fallbackFunction.selector, bytes1(0x00), address(mockHook)) - ) - ); - vm.expectEmit(address(mockFallback)); - emit MockFallback.Foobar(); - uint256 res = MockFallback(address(kernel)).fallbackFunction(10); - assertEq(res, 100); - SelectorManager.SelectorConfig memory c = kernel.selectorConfig(MockFallback.fallbackFunction.selector); - assertEq(address(c.target), address(mockFallback)); - assertEq(address(c.hook), address(mockHook)); - assertTrue(c.callType == CallType.wrap(bytes1(0x00))); - } - - function test_uninstall_selector_call() external unitTest { - kernel.installModule( - 3, - address(mockFallback), - abi.encode( - hex"deadbeef", abi.encodePacked(MockFallback.fallbackFunction.selector, bytes1(0x00), address(1)) - ) - ); - vm.expectEmit(address(mockFallback)); - emit MockFallback.Foobar(); - uint256 res = MockFallback(address(kernel)).fallbackFunction(10); - assertEq(res, 100); - SelectorManager.SelectorConfig memory c = kernel.selectorConfig(MockFallback.fallbackFunction.selector); - assertEq(address(c.target), address(mockFallback)); - assertEq(address(c.hook), address(1)); - assertTrue(c.callType == CallType.wrap(bytes1(0x00))); - kernel.uninstallModule( - 3, address(mockFallback), abi.encode(hex"", abi.encodePacked(MockFallback.fallbackFunction.selector)) - ); - c = kernel.selectorConfig(MockFallback.fallbackFunction.selector); - assertEq(address(c.target), address(0)); - assertEq(address(c.hook), address(0)); - assertTrue(c.callType == CallType.wrap(bytes1(0x00))); - } - - function test_install_selector_call_fail() external unitTest { - kernel.installModule( - 3, - address(mockFallback), - abi.encode( - hex"deadbeef", abi.encodePacked(MockFallback.fallbackFunction.selector, bytes1(0x00), address(1)) - ) - ); - vm.expectRevert(MockFallback.Limit.selector, address(mockFallback)); - MockFallback(address(kernel)).fallbackFunction(100); - } - - function test_install_selector_delegatecall() external unitTest { - kernel.installModule( - 3, - address(mockFallback), - abi.encode( - hex"deadbeef", abi.encodePacked(MockFallback.fallbackFunction.selector, bytes1(0xff), address(1)) - ) - ); - vm.expectEmit(address(kernel)); - emit MockFallback.Foobar(); - uint256 res = MockFallback(address(kernel)).fallbackFunction(10); - assertEq(res, 100); - } - - function test_install_selector_delegatecall_fail() external unitTest { - kernel.installModule( - 3, - address(mockFallback), - abi.encode( - hex"deadbeef", abi.encodePacked(MockFallback.fallbackFunction.selector, bytes1(0xff), address(1)) - ) - ); - vm.expectRevert(MockFallback.Limit.selector, address(kernel)); - MockFallback(address(kernel)).fallbackFunction(100); - } - - function test_install_selector_invalid_selector() external unitTest { - kernel.installModule( - 3, - address(mockFallback), - abi.encode( - hex"deadbeef", abi.encodePacked(MockFallback.fallbackFunction.selector, bytes1(0xff), address(1)) - ) - ); - vm.expectRevert(InvalidSelector.selector, address(kernel)); - MockFallback(address(kernel)).getData(); - } - - function test_execute() external unitTest { - vm.expectEmit(address(callee)); - emit MockCallee.Lorem(); - assertEq(kernel.supportsExecutionMode(bytes32(0)), true); - kernel.execute( - bytes32(0), abi.encodePacked(address(callee), uint256(0), abi.encodeWithSelector(MockCallee.foo.selector)) - ); - assertEq(callee.bar(), 1); - } - - function test_execute_fail() external unitTest { - vm.expectRevert(MockCallee.Haha.selector); - kernel.execute( - bytes32(0), - abi.encodePacked(address(callee), uint256(0), abi.encodeWithSelector(MockCallee.forceRevert.selector)) - ); - } - - function test_execute_fail_invalid_callType() external unitTest { - bytes32 mode = LibERC7579.encodeMode(bytes1(0x02), bytes1(0x01), bytes4(0), bytes22(0)); - assertEq(kernel.supportsExecutionMode(mode), false); - vm.expectRevert(InvalidCallType.selector, address(kernel)); - kernel.execute( - mode, abi.encodePacked(address(callee), uint256(0), abi.encodeWithSelector(MockCallee.foo.selector)) - ); - } - - function test_execute_fail_invalid_execType() external unitTest { - bytes32 mode = LibERC7579.encodeMode(bytes1(0x00), bytes1(0x02), bytes4(0), bytes22(0)); - assertEq(kernel.supportsExecutionMode(mode), false); - vm.expectRevert(InvalidExecType.selector, address(kernel)); - kernel.execute( - mode, abi.encodePacked(address(callee), uint256(0), abi.encodeWithSelector(MockCallee.foo.selector)) - ); - } - - function test_execute_fail_try() external unitTest { - bytes32 mode = LibERC7579.encodeMode(bytes1(0x00), bytes1(0x01), bytes4(0), bytes22(0)); - assertEq(kernel.supportsExecutionMode(mode), true); - kernel.execute( - mode, abi.encodePacked(address(callee), uint256(0), abi.encodeWithSelector(MockCallee.forceRevert.selector)) - ); - } - - function test_execute_batch() external unitTest { - Call[] memory calls = new Call[](2); - calls[0] = Call({to: address(callee), value: 0, data: abi.encodeWithSelector(MockCallee.foo.selector)}); - calls[1] = Call({to: address(callee), value: 0, data: abi.encodeWithSelector(MockCallee.lorem.selector)}); - assertEq(callee.data(), ""); - bytes32 mode = LibERC7579.encodeMode(bytes1(0x01), bytes1(0x00), bytes4(0), bytes22(0)); - assertEq(kernel.supportsExecutionMode(mode), true); - vm.expectEmit(address(callee)); - emit MockCallee.Lorem(); - kernel.execute(mode, abi.encode(calls)); - assertEq(callee.bar(), 1); - assertEq(callee.data(), "lorem ipsum"); - } - - function test_execute_batch_fail() external unitTest { - Call[] memory calls = new Call[](2); - calls[0] = Call({to: address(callee), value: 0, data: abi.encodeWithSelector(MockCallee.foo.selector)}); - calls[1] = Call({to: address(callee), value: 0, data: abi.encodeWithSelector(MockCallee.forceRevert.selector)}); - assertEq(callee.data(), ""); - bytes32 mode = LibERC7579.encodeMode(bytes1(0x01), bytes1(0x00), bytes4(0), bytes22(0)); - assertEq(kernel.supportsExecutionMode(mode), true); - vm.expectRevert(MockCallee.Haha.selector); - kernel.execute(LibERC7579.encodeMode(bytes1(0x01), bytes1(0x00), bytes4(0), bytes22(0)), abi.encode(calls)); - } - - function test_execute_batch_fail_try() external unitTest { - Call[] memory calls = new Call[](2); - calls[0] = Call({to: address(callee), value: 0, data: abi.encodeWithSelector(MockCallee.foo.selector)}); - calls[1] = Call({to: address(callee), value: 0, data: abi.encodeWithSelector(MockCallee.forceRevert.selector)}); - assertEq(callee.data(), ""); - bytes32 mode = LibERC7579.encodeMode(bytes1(0x01), bytes1(0x01), bytes4(0), bytes22(0)); - assertEq(kernel.supportsExecutionMode(mode), true); - kernel.execute(LibERC7579.encodeMode(bytes1(0x01), bytes1(0x01), bytes4(0), bytes22(0)), abi.encode(calls)); - assertEq(callee.bar(), 1); - } - - function test_execute_delegatecall() external unitTest { - bytes32 mode = LibERC7579.encodeMode(bytes1(0xff), bytes1(0x00), bytes4(0), bytes22(0)); - assertEq(kernel.supportsExecutionMode(mode), true); - vm.expectEmit(address(kernel)); - emit MockCallee.Lorem(); - kernel.execute( - LibERC7579.encodeMode(bytes1(0xff), bytes1(0x00), bytes4(0), bytes22(0)), - abi.encodePacked(address(callee), abi.encodeWithSelector(MockCallee.foo.selector)) - ); - } - - function test_execute_delegatecall_fail() external unitTest { - vm.expectRevert(MockCallee.Haha.selector); - kernel.execute( - LibERC7579.encodeMode(bytes1(0xff), bytes1(0x00), bytes4(0), bytes22(0)), - abi.encodePacked(address(callee), abi.encodeWithSelector(MockCallee.forceRevert.selector)) - ); - } - - function test_execute_delegatecall_fail_try() external unitTest { - bytes32 mode = LibERC7579.encodeMode(bytes1(0xff), bytes1(0x01), bytes4(0), bytes22(0)); - assertEq(kernel.supportsExecutionMode(mode), true); - kernel.execute( - LibERC7579.encodeMode(bytes1(0xff), bytes1(0x01), bytes4(0), bytes22(0)), - abi.encodePacked(address(callee), abi.encodeWithSelector(MockCallee.forceRevert.selector)) - ); - } - - function test_execute_from_executor() external unitTestExecutor { - vm.expectEmit(address(callee)); - emit MockCallee.Lorem(); - kernel.executeFromExecutor( - bytes32(0), abi.encodePacked(address(callee), uint256(0), abi.encodeWithSelector(MockCallee.foo.selector)) - ); - assertEq(callee.bar(), 1); - } - - function test_execute_batch_from_executor() external unitTestExecutor { - Call[] memory calls = new Call[](2); - calls[0] = Call({to: address(callee), value: 0, data: abi.encodeWithSelector(MockCallee.foo.selector)}); - calls[1] = Call({to: address(callee), value: 0, data: abi.encodeWithSelector(MockCallee.lorem.selector)}); - assertEq(callee.data(), ""); - vm.expectEmit(address(callee)); - emit MockCallee.Lorem(); - kernel.executeFromExecutor( - LibERC7579.encodeMode(bytes1(0x01), bytes1(0x00), bytes4(0), bytes22(0)), abi.encode(calls) - ); - assertEq(callee.bar(), 1); - assertEq(callee.data(), "lorem ipsum"); - } - - bytes32 constant MODE_EXECUTE_WITH_OP_DATA = bytes10(0x01000000000078210001); - - function encodeInstallWithExecute(Call[] memory calls, bool replayable, uint256 nonce, Install[] memory packages) - internal - returns (bytes memory sig) - { - InstallAndExecute memory ie = - InstallAndExecute({replayable: replayable, nonce: nonce, packages: packages, signature: hex""}); - bytes32 hash = helper.installAndExecuteDigest(address(kernel), MODE_EXECUTE_WITH_OP_DATA, calls, ie); - - MockKernel mockKernel = new MockKernel(ep); - - if (!is7702) { - vm.store(address(kernel), ERC1967_IMPLEMENTATION_SLOT, bytes32(uint256(uint160(address(mockKernel))))); - assertEq( - MockKernel(payable(address(kernel))).installAndExecuteDigest(MODE_EXECUTE_WITH_OP_DATA, calls, ie), hash - ); - } - sig = abi.encode(false, uint256(0), packages, _rootSignHash(hash, true)); - } - - function test_execute_batch_from_executor_with_install_data() external { - address newExecutor = makeAddr("New Executor"); - Install[] memory packages = new Install[](1); - packages[0] = Install({moduleType: 2, module: newExecutor, internalData: hex"", moduleData: hex""}); - - Call[] memory calls = new Call[](2); - calls[0] = Call({to: address(callee), value: 0, data: abi.encodeWithSelector(MockCallee.foo.selector)}); - calls[1] = Call({to: address(callee), value: 0, data: abi.encodeWithSelector(MockCallee.lorem.selector)}); - assertEq(callee.data(), ""); - vm.startPrank(newExecutor); - bytes memory installData = encodeInstallWithExecute(calls, false, uint256(0), packages); - vm.expectEmit(address(callee)); - emit MockCallee.Lorem(); - kernel.executeFromExecutor(MODE_EXECUTE_WITH_OP_DATA, abi.encode(calls, installData)); - assertEq(callee.bar(), 1); - assertEq(callee.data(), "lorem ipsum"); - vm.stopPrank(); - } - - function test_execute_delegatecall_from_executor() external unitTestExecutor { - vm.expectEmit(address(kernel)); - emit MockCallee.Lorem(); - kernel.executeFromExecutor( - LibERC7579.encodeMode(bytes1(0xff), bytes1(0x00), bytes4(0), bytes22(0)), - abi.encodePacked(address(callee), abi.encodeWithSelector(MockCallee.foo.selector)) - ); - } - - // Code heavily inspired by solady's erc1271, erc4337 test file - bytes32 internal constant _DOMAIN_SEP_B = 0xa1a044077d7677adbbfa892ded5390979b33993e0e2a457e3f974bbcda53821b; - - function _erc1271Signature( - bytes32 hash, - bytes memory contentsType, - bytes memory contentsName, - function(bytes32, bool) returns(bytes memory) signFn, - bool isExplicit, - bool success - ) internal returns (bytes32 contentsHash, bytes memory sig) { - contentsHash = keccak256(abi.encode(hash, contentsType)); - bytes32 actualHash; - if (isExplicit) { - actualHash = _toERC1271Hash(address(kernel), contentsHash, contentsType, contentsName); - } else { - actualHash = _toERC1271Hash(address(kernel), contentsHash, contentsType, _contentsName(contentsType)); - } - sig = signFn(actualHash, success); - bytes memory contentsDescription = abi.encodePacked(contentsType, contentsName); - - sig = - abi.encodePacked(sig, _DOMAIN_SEP_B, contentsHash, contentsDescription, uint16(contentsDescription.length)); - } - - function _toERC1271Hash(address account, bytes32 contents, bytes memory contentsType, bytes memory contentsName) - internal - view - returns (bytes32) - { - bytes32 parentStructHash = keccak256( - abi.encodePacked( - abi.encode(_typedDataSignTypeHash(contentsType, contentsName), contents), - _accountDomainStructFields(account) - ) - ); - return keccak256(abi.encodePacked("\x19\x01", _DOMAIN_SEP_B, parentStructHash)); - } - - struct _AccountDomainStruct { - string name; - string version; - uint256 chainId; - address verifyingContract; - bytes32 salt; - } - - function _toContentsHash(bytes32 contents) internal pure returns (bytes32) { - return keccak256(abi.encodePacked(hex"1901", _DOMAIN_SEP_B, contents)); - } - - function _accountDomainStructFields(address account) internal view returns (bytes memory) { - _AccountDomainStruct memory t; - (, t.name, t.version, t.chainId, t.verifyingContract, t.salt,) = kernel.eip712Domain(); - - return abi.encode(keccak256(bytes(t.name)), keccak256(bytes(t.version)), t.chainId, t.verifyingContract, t.salt); - } - - function _toERC1271HashPersonalSign(bytes32 childHash) internal view returns (bytes32) { - _AccountDomainStruct memory t; - (, t.name, t.version, t.chainId, t.verifyingContract, t.salt,) = kernel.eip712Domain(); - - bytes32 domainSeparator = keccak256( - abi.encode( - keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), - keccak256(abi.encodePacked(t.name)), - keccak256(abi.encodePacked(t.version)), - t.chainId, - t.verifyingContract - ) - ); - bytes32 parentStructHash = keccak256(abi.encode(keccak256("PersonalSign(bytes prefixed)"), childHash)); - return keccak256(abi.encodePacked("\x19\x01", domainSeparator, parentStructHash)); - } - - function _typedDataSignTypeHash(bytes memory contentsType, bytes memory contentsName) - internal - pure - returns (bytes32) - { - return keccak256( - abi.encodePacked( - "TypedDataSign(", - contentsName, - " contents,string name,string version,uint256 chainId,address verifyingContract,bytes32 salt)", - contentsType - ) - ); - } - - function _contentsName(bytes memory contentsType) internal pure returns (bytes memory) { - string memory ct = string(contentsType); - return bytes(LibString.slice(ct, 0, LibString.indexOf(ct, "(", 0))); - } } diff --git a/test/KernelERC1271Test.sol b/test/KernelERC1271Test.sol new file mode 100644 index 00000000..f9fffb6f --- /dev/null +++ b/test/KernelERC1271Test.sol @@ -0,0 +1,259 @@ +pragma solidity ^0.8.0; + +import {Test} from "forge-std/Test.sol"; +import {EntryPointLib} from "./utils/EntryPointLib.sol"; +import {IEntryPoint} from "account-abstraction/interfaces/IEntryPoint.sol"; +import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; +import {Kernel} from "src/Kernel.sol"; +import {KernelUUPS} from "src/KernelUUPS.sol"; +import {KernelHelper} from "src/KernelHelper.sol"; +import {SelectorManager} from "src/core/SelectorManager.sol"; +import {KernelFactory} from "src/KernelFactory.sol"; +import {KernelUUPS} from "src/KernelUUPS.sol"; +import {KernelImmutableECDSA} from "src/KernelImmutableECDSA.sol"; +import {LibERC7579} from "solady/accounts/LibERC7579.sol"; +import {LibString} from "solady/utils/LibString.sol"; +import {Install} from "src/types/Structs.sol"; +import {MockFallback} from "./mock/MockFallback.sol"; +import {MockExecutor} from "./mock/MockExecutor.sol"; +import {MockValidator} from "./mock/MockValidator.sol"; +import {MockHook} from "./mock/MockHook.sol"; +import {MockPolicy} from "./mock/MockPolicy.sol"; +import {MockSigner} from "./mock/MockSigner.sol"; +import {MockERC721} from "./mock/MockERC721.sol"; +import {MockERC1155} from "./mock/MockERC1155.sol"; +import {MockCallee} from "./mock/MockCallee.sol"; +import {MockKernel} from "./mock/MockKernel.sol"; +import {IHook, IValidator} from "src/interfaces/IERC7579Modules.sol"; +import {CallType} from "src/types/Types.sol"; +import "src/types/Constants.sol"; +import "forge-std/console.sol"; +import "src/types/Error.sol"; +import "src/types/Events.sol"; +import "src/types/Structs.sol"; +import {KernelTestBase} from "./KernelTestBase.sol"; + +abstract contract KernelERC1271Test is KernelTestBase { + function test_erc7739() public { + assertEq( + kernel.isValidSignature(0x7739773977397739773977397739773977397739773977397739773977397739, ""), + bytes4(0x77390001) + ); + } + + function test_erc1271_root() external unitTest { + bytes32 messageHash = keccak256("Hello world"); + (bytes32 contentsHash, bytes memory sig) = + _erc1271Signature(messageHash, "C(bytes32 stuff)", "", _rootSignHash, false, true); + bytes4 ret = kernel.isValidSignature(_toContentsHash(contentsHash), abi.encodePacked(bytes20(0), sig)); + assertEq(ret, ERC1271_MAGICVALUE); + } + + function test_erc1271_fail_invalid() external unitTest { + bytes32 messageHash = keccak256("Hello world"); + (bytes32 contentsHash, bytes memory sig) = + _erc1271Signature(messageHash, "C(bytes32 stuff)", "", _rootSignHash, false, true); + bytes4 ret = + kernel.isValidSignature(_toContentsHash(contentsHash), abi.encodePacked(bytes20(address(this)), sig)); + assertEq(ret, ERC1271_INVALID); + } + + function test_erc1271_root_fail() external unitTest { + bytes32 messageHash = keccak256("Hello world"); + (bytes32 contentsHash, bytes memory sig) = + _erc1271Signature(messageHash, "C(bytes32 stuff)", "", _rootSignHash, false, false); + bytes4 ret = kernel.isValidSignature(_toContentsHash(contentsHash), abi.encodePacked(bytes20(0), sig)); + assertEq(ret, ERC1271_INVALID); + } + + function test_erc1271_root_personal_sign() external unitTest { + bytes32 messageHash = keccak256("Hello world"); + bytes32 personalHash = _toERC1271HashPersonalSign(messageHash); + bytes memory sig = _rootSignHash(personalHash, true); + bytes4 ret = kernel.isValidSignature(messageHash, abi.encodePacked(bytes20(0), sig)); + assertEq(ret, ERC1271_MAGICVALUE); + } + + function test_erc1271_root_personal_sign_fail() external unitTest { + bytes32 messageHash = keccak256("Hello world"); + bytes32 personalHash = _toERC1271HashPersonalSign(messageHash); + bytes memory sig = _rootSignHash(personalHash, false); + bytes4 ret = kernel.isValidSignature(messageHash, abi.encodePacked(bytes20(0), sig)); + assertEq(ret, ERC1271_INVALID); + } + + function test_erc1271_validator() external unitTest { + bytes32 messageHash = keccak256("Hello world"); + (bytes32 contentsHash, bytes memory sig) = + _erc1271Signature(messageHash, "C(bytes32 stuff)", "", _validatorSignHash, false, true); + kernel.installModule(1, address(newValidator), abi.encode(hex"", hex"")); + bytes4 ret = kernel.isValidSignature( + _toContentsHash(contentsHash), abi.encodePacked(bytes20(address(newValidator)), sig) + ); + assertEq(ret, ERC1271_MAGICVALUE); + } + + function test_erc1271_validator_fail() external unitTest { + bytes32 messageHash = keccak256("Hello world"); + (bytes32 contentsHash, bytes memory sig) = + _erc1271Signature(messageHash, "C(bytes32 stuff)", "", _validatorSignHash, false, false); + kernel.installModule(1, address(newValidator), abi.encode(hex"", hex"")); + bytes4 ret = kernel.isValidSignature( + _toContentsHash(contentsHash), abi.encodePacked(bytes20(address(newValidator)), sig) + ); + assertEq(ret, ERC1271_INVALID); + } + + function test_erc1271_validator_personal_sign() external unitTest { + bytes32 messageHash = keccak256("Hello world"); + bytes32 personalHash = _toERC1271HashPersonalSign(messageHash); + bytes memory sig = _validatorSignHash(personalHash, true); + kernel.installModule(1, address(newValidator), abi.encode(hex"", hex"")); + bytes4 ret = kernel.isValidSignature(messageHash, abi.encodePacked(bytes20(address(newValidator)), sig)); + assertEq(ret, ERC1271_MAGICVALUE); + } + + function test_erc1271_validator_personal_sign_fail() external unitTest { + bytes32 messageHash = keccak256("Hello world"); + bytes32 personalHash = _toERC1271HashPersonalSign(messageHash); + bytes memory sig = _validatorSignHash(personalHash, false); + kernel.installModule(1, address(newValidator), abi.encode(hex"", hex"")); + bytes4 ret = kernel.isValidSignature(messageHash, abi.encodePacked(bytes20(address(newValidator)), sig)); + assertEq(ret, ERC1271_INVALID); + } + + function test_erc1271_permission() external unitTest { + bytes32 messageHash = keccak256("Hello world"); + (bytes32 contentsHash, bytes memory sig) = + _erc1271Signature(messageHash, "C(bytes32 stuff)", "", _permissionSignHash, false, true); + kernel.installModule(5, address(policy), abi.encode(hex"deadbeef", abi.encodePacked(permissionId))); + kernel.installModule(6, address(signer), abi.encode(hex"deadbeef", abi.encodePacked(permissionId))); + bytes4 ret = kernel.isValidSignature(_toContentsHash(contentsHash), abi.encodePacked(permissionId, sig)); + assertEq(ret, ERC1271_MAGICVALUE); + } + + function test_erc1271_permission_fail() external unitTest { + bytes32 messageHash = keccak256("Hello world"); + (bytes32 contentsHash, bytes memory sig) = + _erc1271Signature(messageHash, "C(bytes32 stuff)", "", _permissionSignHash, false, false); + kernel.installModule(5, address(policy), abi.encode(hex"deadbeef", abi.encodePacked(permissionId))); + kernel.installModule(6, address(signer), abi.encode(hex"deadbeef", abi.encodePacked(permissionId))); + bytes4 ret = kernel.isValidSignature(_toContentsHash(contentsHash), abi.encodePacked(permissionId, sig)); + assertEq(ret, ERC1271_INVALID); + } + + function test_erc1271_permission_personal_sign() external unitTest { + bytes32 messageHash = keccak256("Hello world"); + bytes32 personalHash = _toERC1271HashPersonalSign(messageHash); + bytes memory sig = _permissionSignHash(personalHash, true); + kernel.installModule(5, address(policy), abi.encode(hex"deadbeef", abi.encodePacked(permissionId))); + kernel.installModule(6, address(signer), abi.encode(hex"deadbeef", abi.encodePacked(permissionId))); + bytes4 ret = kernel.isValidSignature(messageHash, abi.encodePacked(permissionId, sig)); + assertEq(ret, ERC1271_MAGICVALUE); + } + + function test_erc1271_permission_personal_sign_fail() external unitTest { + bytes32 messageHash = keccak256("Hello world"); + bytes32 personalHash = _toERC1271HashPersonalSign(messageHash); + bytes memory sig = _permissionSignHash(personalHash, false); + kernel.installModule(5, address(policy), abi.encode(hex"deadbeef", abi.encodePacked(permissionId))); + kernel.installModule(6, address(signer), abi.encode(hex"deadbeef", abi.encodePacked(permissionId))); + bytes4 ret = kernel.isValidSignature(messageHash, abi.encodePacked(permissionId, sig)); + assertEq(ret, ERC1271_INVALID); + } + + // Code heavily inspired by solady's erc1271, erc4337 test file + bytes32 internal constant _DOMAIN_SEP_B = 0xa1a044077d7677adbbfa892ded5390979b33993e0e2a457e3f974bbcda53821b; + + function _erc1271Signature( + bytes32 hash, + bytes memory contentsType, + bytes memory contentsName, + function(bytes32, bool) returns(bytes memory) signFn, + bool isExplicit, + bool success + ) internal returns (bytes32 contentsHash, bytes memory sig) { + contentsHash = keccak256(abi.encode(hash, contentsType)); + bytes32 actualHash; + if (isExplicit) { + actualHash = _toERC1271Hash(address(kernel), contentsHash, contentsType, contentsName); + } else { + actualHash = _toERC1271Hash(address(kernel), contentsHash, contentsType, _contentsName(contentsType)); + } + sig = signFn(actualHash, success); + bytes memory contentsDescription = abi.encodePacked(contentsType, contentsName); + + sig = + abi.encodePacked(sig, _DOMAIN_SEP_B, contentsHash, contentsDescription, uint16(contentsDescription.length)); + } + + function _toERC1271Hash(address account, bytes32 contents, bytes memory contentsType, bytes memory contentsName) + internal + view + returns (bytes32) + { + bytes32 parentStructHash = keccak256( + abi.encodePacked( + abi.encode(_typedDataSignTypeHash(contentsType, contentsName), contents), + _accountDomainStructFields(account) + ) + ); + return keccak256(abi.encodePacked("\x19\x01", _DOMAIN_SEP_B, parentStructHash)); + } + + struct _AccountDomainStruct { + string name; + string version; + uint256 chainId; + address verifyingContract; + bytes32 salt; + } + + function _toContentsHash(bytes32 contents) internal pure returns (bytes32) { + return keccak256(abi.encodePacked(hex"1901", _DOMAIN_SEP_B, contents)); + } + + function _accountDomainStructFields(address account) internal view returns (bytes memory) { + _AccountDomainStruct memory t; + (, t.name, t.version, t.chainId, t.verifyingContract, t.salt,) = kernel.eip712Domain(); + + return abi.encode(keccak256(bytes(t.name)), keccak256(bytes(t.version)), t.chainId, t.verifyingContract, t.salt); + } + + function _toERC1271HashPersonalSign(bytes32 childHash) internal view returns (bytes32) { + _AccountDomainStruct memory t; + (, t.name, t.version, t.chainId, t.verifyingContract, t.salt,) = kernel.eip712Domain(); + + bytes32 domainSeparator = keccak256( + abi.encode( + keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), + keccak256(abi.encodePacked(t.name)), + keccak256(abi.encodePacked(t.version)), + t.chainId, + t.verifyingContract + ) + ); + bytes32 parentStructHash = keccak256(abi.encode(keccak256("PersonalSign(bytes prefixed)"), childHash)); + return keccak256(abi.encodePacked("\x19\x01", domainSeparator, parentStructHash)); + } + + function _typedDataSignTypeHash(bytes memory contentsType, bytes memory contentsName) + internal + pure + returns (bytes32) + { + return keccak256( + abi.encodePacked( + "TypedDataSign(", + contentsName, + " contents,string name,string version,uint256 chainId,address verifyingContract,bytes32 salt)", + contentsType + ) + ); + } + + function _contentsName(bytes memory contentsType) internal pure returns (bytes memory) { + string memory ct = string(contentsType); + return bytes(LibString.slice(ct, 0, LibString.indexOf(ct, "(", 0))); + } +} diff --git a/test/KernelExecuteTest.sol b/test/KernelExecuteTest.sol new file mode 100644 index 00000000..da6d848d --- /dev/null +++ b/test/KernelExecuteTest.sol @@ -0,0 +1,144 @@ +pragma solidity ^0.8.0; + +import {Test} from "forge-std/Test.sol"; +import {EntryPointLib} from "./utils/EntryPointLib.sol"; +import {IEntryPoint} from "account-abstraction/interfaces/IEntryPoint.sol"; +import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; +import {Kernel} from "src/Kernel.sol"; +import {KernelUUPS} from "src/KernelUUPS.sol"; +import {KernelHelper} from "src/KernelHelper.sol"; +import {SelectorManager} from "src/core/SelectorManager.sol"; +import {KernelFactory} from "src/KernelFactory.sol"; +import {KernelUUPS} from "src/KernelUUPS.sol"; +import {KernelImmutableECDSA} from "src/KernelImmutableECDSA.sol"; +import {LibERC7579} from "solady/accounts/LibERC7579.sol"; +import {LibString} from "solady/utils/LibString.sol"; +import {Install} from "src/types/Structs.sol"; +import {MockFallback} from "./mock/MockFallback.sol"; +import {MockExecutor} from "./mock/MockExecutor.sol"; +import {MockValidator} from "./mock/MockValidator.sol"; +import {MockHook} from "./mock/MockHook.sol"; +import {MockPolicy} from "./mock/MockPolicy.sol"; +import {MockSigner} from "./mock/MockSigner.sol"; +import {MockERC721} from "./mock/MockERC721.sol"; +import {MockERC1155} from "./mock/MockERC1155.sol"; +import {MockCallee} from "./mock/MockCallee.sol"; +import {MockKernel} from "./mock/MockKernel.sol"; +import {IHook, IValidator} from "src/interfaces/IERC7579Modules.sol"; +import {CallType} from "src/types/Types.sol"; +import "src/types/Constants.sol"; +import "forge-std/console.sol"; +import "src/types/Error.sol"; +import "src/types/Events.sol"; +import "src/types/Structs.sol"; +import {KernelTestBase} from "./KernelTestBase.sol"; + +abstract contract KernelExecuteTest is KernelTestBase { + function test_execute() external unitTest { + vm.expectEmit(address(callee)); + emit MockCallee.Lorem(); + assertEq(kernel.supportsExecutionMode(bytes32(0)), true); + kernel.execute( + bytes32(0), abi.encodePacked(address(callee), uint256(0), abi.encodeWithSelector(MockCallee.foo.selector)) + ); + assertEq(callee.bar(), 1); + } + + function test_execute_fail() external unitTest { + vm.expectRevert(MockCallee.Haha.selector); + kernel.execute( + bytes32(0), + abi.encodePacked(address(callee), uint256(0), abi.encodeWithSelector(MockCallee.forceRevert.selector)) + ); + } + + function test_execute_fail_invalid_callType() external unitTest { + bytes32 mode = LibERC7579.encodeMode(bytes1(0x02), bytes1(0x01), bytes4(0), bytes22(0)); + assertEq(kernel.supportsExecutionMode(mode), false); + vm.expectRevert(InvalidCallType.selector, address(kernel)); + kernel.execute( + mode, abi.encodePacked(address(callee), uint256(0), abi.encodeWithSelector(MockCallee.foo.selector)) + ); + } + + function test_execute_fail_invalid_execType() external unitTest { + bytes32 mode = LibERC7579.encodeMode(bytes1(0x00), bytes1(0x02), bytes4(0), bytes22(0)); + assertEq(kernel.supportsExecutionMode(mode), false); + vm.expectRevert(InvalidExecType.selector, address(kernel)); + kernel.execute( + mode, abi.encodePacked(address(callee), uint256(0), abi.encodeWithSelector(MockCallee.foo.selector)) + ); + } + + function test_execute_fail_try() external unitTest { + bytes32 mode = LibERC7579.encodeMode(bytes1(0x00), bytes1(0x01), bytes4(0), bytes22(0)); + assertEq(kernel.supportsExecutionMode(mode), true); + kernel.execute( + mode, abi.encodePacked(address(callee), uint256(0), abi.encodeWithSelector(MockCallee.forceRevert.selector)) + ); + } + + function test_execute_batch() external unitTest { + Call[] memory calls = new Call[](2); + calls[0] = Call({to: address(callee), value: 0, data: abi.encodeWithSelector(MockCallee.foo.selector)}); + calls[1] = Call({to: address(callee), value: 0, data: abi.encodeWithSelector(MockCallee.lorem.selector)}); + assertEq(callee.data(), ""); + bytes32 mode = LibERC7579.encodeMode(bytes1(0x01), bytes1(0x00), bytes4(0), bytes22(0)); + assertEq(kernel.supportsExecutionMode(mode), true); + vm.expectEmit(address(callee)); + emit MockCallee.Lorem(); + kernel.execute(mode, abi.encode(calls)); + assertEq(callee.bar(), 1); + assertEq(callee.data(), "lorem ipsum"); + } + + function test_execute_batch_fail() external unitTest { + Call[] memory calls = new Call[](2); + calls[0] = Call({to: address(callee), value: 0, data: abi.encodeWithSelector(MockCallee.foo.selector)}); + calls[1] = Call({to: address(callee), value: 0, data: abi.encodeWithSelector(MockCallee.forceRevert.selector)}); + assertEq(callee.data(), ""); + bytes32 mode = LibERC7579.encodeMode(bytes1(0x01), bytes1(0x00), bytes4(0), bytes22(0)); + assertEq(kernel.supportsExecutionMode(mode), true); + vm.expectRevert(MockCallee.Haha.selector); + kernel.execute(LibERC7579.encodeMode(bytes1(0x01), bytes1(0x00), bytes4(0), bytes22(0)), abi.encode(calls)); + } + + function test_execute_batch_fail_try() external unitTest { + Call[] memory calls = new Call[](2); + calls[0] = Call({to: address(callee), value: 0, data: abi.encodeWithSelector(MockCallee.foo.selector)}); + calls[1] = Call({to: address(callee), value: 0, data: abi.encodeWithSelector(MockCallee.forceRevert.selector)}); + assertEq(callee.data(), ""); + bytes32 mode = LibERC7579.encodeMode(bytes1(0x01), bytes1(0x01), bytes4(0), bytes22(0)); + assertEq(kernel.supportsExecutionMode(mode), true); + kernel.execute(LibERC7579.encodeMode(bytes1(0x01), bytes1(0x01), bytes4(0), bytes22(0)), abi.encode(calls)); + assertEq(callee.bar(), 1); + } + + function test_execute_delegatecall() external unitTest { + bytes32 mode = LibERC7579.encodeMode(bytes1(0xff), bytes1(0x00), bytes4(0), bytes22(0)); + assertEq(kernel.supportsExecutionMode(mode), true); + vm.expectEmit(address(kernel)); + emit MockCallee.Lorem(); + kernel.execute( + LibERC7579.encodeMode(bytes1(0xff), bytes1(0x00), bytes4(0), bytes22(0)), + abi.encodePacked(address(callee), abi.encodeWithSelector(MockCallee.foo.selector)) + ); + } + + function test_execute_delegatecall_fail() external unitTest { + vm.expectRevert(MockCallee.Haha.selector); + kernel.execute( + LibERC7579.encodeMode(bytes1(0xff), bytes1(0x00), bytes4(0), bytes22(0)), + abi.encodePacked(address(callee), abi.encodeWithSelector(MockCallee.forceRevert.selector)) + ); + } + + function test_execute_delegatecall_fail_try() external unitTest { + bytes32 mode = LibERC7579.encodeMode(bytes1(0xff), bytes1(0x01), bytes4(0), bytes22(0)); + assertEq(kernel.supportsExecutionMode(mode), true); + kernel.execute( + LibERC7579.encodeMode(bytes1(0xff), bytes1(0x01), bytes4(0), bytes22(0)), + abi.encodePacked(address(callee), abi.encodeWithSelector(MockCallee.forceRevert.selector)) + ); + } +} diff --git a/test/KernelExecutorTest.sol b/test/KernelExecutorTest.sol new file mode 100644 index 00000000..1c6a8975 --- /dev/null +++ b/test/KernelExecutorTest.sol @@ -0,0 +1,139 @@ +pragma solidity ^0.8.0; + +import {Test} from "forge-std/Test.sol"; +import {EntryPointLib} from "./utils/EntryPointLib.sol"; +import {IEntryPoint} from "account-abstraction/interfaces/IEntryPoint.sol"; +import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; +import {Kernel} from "src/Kernel.sol"; +import {KernelUUPS} from "src/KernelUUPS.sol"; +import {KernelHelper} from "src/KernelHelper.sol"; +import {SelectorManager} from "src/core/SelectorManager.sol"; +import {KernelFactory} from "src/KernelFactory.sol"; +import {KernelUUPS} from "src/KernelUUPS.sol"; +import {KernelImmutableECDSA} from "src/KernelImmutableECDSA.sol"; +import {LibERC7579} from "solady/accounts/LibERC7579.sol"; +import {LibString} from "solady/utils/LibString.sol"; +import {Install} from "src/types/Structs.sol"; +import {MockFallback} from "./mock/MockFallback.sol"; +import {MockExecutor} from "./mock/MockExecutor.sol"; +import {MockValidator} from "./mock/MockValidator.sol"; +import {MockHook} from "./mock/MockHook.sol"; +import {MockPolicy} from "./mock/MockPolicy.sol"; +import {MockSigner} from "./mock/MockSigner.sol"; +import {MockERC721} from "./mock/MockERC721.sol"; +import {MockERC1155} from "./mock/MockERC1155.sol"; +import {MockCallee} from "./mock/MockCallee.sol"; +import {MockKernel} from "./mock/MockKernel.sol"; +import {IHook, IValidator} from "src/interfaces/IERC7579Modules.sol"; +import {CallType} from "src/types/Types.sol"; +import "src/types/Constants.sol"; +import "forge-std/console.sol"; +import "src/types/Error.sol"; +import "src/types/Events.sol"; +import "src/types/Structs.sol"; +import {KernelTestBase} from "./KernelTestBase.sol"; + +abstract contract KernelExecutorTest is KernelTestBase { + function test_install_executor_oninstall_success() external unitTest { + assertTrue(kernel.supportsModule(2)); + address newEx = address(new MockExecutor()); + kernel.installModule(2, newEx, abi.encode(hex"deadbeef", "")); + assertEq(address(kernel.executorConfig(newEx).hook), address(1)); + assertTrue(kernel.isModuleInstalled(2, newEx, hex"")); + } + + function test_install_executor_oninstall_fail() external unitTest { + address newEx = makeAddr("New Executor"); + kernel.installModule(2, newEx, abi.encode(hex"", "")); + assertEq(address(kernel.executorConfig(newEx).hook), address(1)); + assertTrue(kernel.isModuleInstalled(2, newEx, hex"")); + } + + function test_uninstall_executor_onuninstall_success() external unitTest { + address newEx = address(new MockExecutor()); + kernel.installModule(2, newEx, abi.encode(hex"deadbeef", "")); + assertEq(address(kernel.executorConfig(newEx).hook), address(1)); + kernel.uninstallModule(2, newEx, abi.encode(hex"", hex"")); + assertEq(address(kernel.executorConfig(newEx).hook), address(0)); + } + + function test_uninstall_executor_onuninstall_fail() external unitTest { + address newEx = makeAddr("New Executor"); + kernel.installModule(2, newEx, abi.encode(hex"", "")); + assertEq(address(kernel.executorConfig(newEx).hook), address(1)); + kernel.uninstallModule(2, newEx, abi.encode(hex"", hex"")); + assertEq(address(kernel.executorConfig(newEx).hook), address(0)); + } + + function test_execute_from_executor() external unitTestExecutor { + vm.expectEmit(address(callee)); + emit MockCallee.Lorem(); + kernel.executeFromExecutor( + bytes32(0), abi.encodePacked(address(callee), uint256(0), abi.encodeWithSelector(MockCallee.foo.selector)) + ); + assertEq(callee.bar(), 1); + } + + function test_execute_batch_from_executor() external unitTestExecutor { + Call[] memory calls = new Call[](2); + calls[0] = Call({to: address(callee), value: 0, data: abi.encodeWithSelector(MockCallee.foo.selector)}); + calls[1] = Call({to: address(callee), value: 0, data: abi.encodeWithSelector(MockCallee.lorem.selector)}); + assertEq(callee.data(), ""); + vm.expectEmit(address(callee)); + emit MockCallee.Lorem(); + kernel.executeFromExecutor( + LibERC7579.encodeMode(bytes1(0x01), bytes1(0x00), bytes4(0), bytes22(0)), abi.encode(calls) + ); + assertEq(callee.bar(), 1); + assertEq(callee.data(), "lorem ipsum"); + } + + bytes32 constant MODE_EXECUTE_WITH_OP_DATA = bytes10(0x01000000000078210001); + + function encodeInstallWithExecute(Call[] memory calls, bool replayable, uint256 nonce, Install[] memory packages) + internal + returns (bytes memory sig) + { + InstallAndExecute memory ie = + InstallAndExecute({replayable: replayable, nonce: nonce, packages: packages, signature: hex""}); + bytes32 hash = helper.installAndExecuteDigest(address(kernel), MODE_EXECUTE_WITH_OP_DATA, calls, ie); + + MockKernel mockKernel = new MockKernel(ep); + + if (!is7702) { + vm.store(address(kernel), ERC1967_IMPLEMENTATION_SLOT, bytes32(uint256(uint160(address(mockKernel))))); + assertEq( + MockKernel(payable(address(kernel))).installAndExecuteDigest(MODE_EXECUTE_WITH_OP_DATA, calls, ie), hash + ); + } + sig = abi.encode(false, uint256(0), packages, _rootSignHash(hash, true)); + } + + function test_execute_batch_from_executor_with_install_data() external { + address newExecutor = makeAddr("New Executor"); + Install[] memory packages = new Install[](1); + packages[0] = Install({moduleType: 2, module: newExecutor, internalData: hex"", moduleData: hex""}); + + Call[] memory calls = new Call[](2); + calls[0] = Call({to: address(callee), value: 0, data: abi.encodeWithSelector(MockCallee.foo.selector)}); + calls[1] = Call({to: address(callee), value: 0, data: abi.encodeWithSelector(MockCallee.lorem.selector)}); + assertEq(callee.data(), ""); + vm.startPrank(newExecutor); + bytes memory installData = encodeInstallWithExecute(calls, false, uint256(0), packages); + vm.expectEmit(address(callee)); + emit MockCallee.Lorem(); + kernel.executeFromExecutor(MODE_EXECUTE_WITH_OP_DATA, abi.encode(calls, installData)); + assertEq(callee.bar(), 1); + assertEq(callee.data(), "lorem ipsum"); + vm.stopPrank(); + } + + function test_execute_delegatecall_from_executor() external unitTestExecutor { + vm.expectEmit(address(kernel)); + emit MockCallee.Lorem(); + kernel.executeFromExecutor( + LibERC7579.encodeMode(bytes1(0xff), bytes1(0x00), bytes4(0), bytes22(0)), + abi.encodePacked(address(callee), abi.encodeWithSelector(MockCallee.foo.selector)) + ); + } +} diff --git a/test/KernelFactory.t.sol b/test/KernelFactory.t.sol new file mode 100644 index 00000000..feb5345e --- /dev/null +++ b/test/KernelFactory.t.sol @@ -0,0 +1,125 @@ +pragma solidity ^0.8.0; + +import {Test} from "forge-std/Test.sol"; +import {EntryPointLib} from "./utils/EntryPointLib.sol"; +import {IEntryPoint} from "account-abstraction/interfaces/IEntryPoint.sol"; +import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; +import {Kernel} from "src/Kernel.sol"; +import {KernelUUPS} from "src/KernelUUPS.sol"; +import {KernelHelper} from "src/KernelHelper.sol"; +import {SelectorManager} from "src/core/SelectorManager.sol"; +import {KernelFactory} from "src/KernelFactory.sol"; +import {KernelUUPS} from "src/KernelUUPS.sol"; +import {KernelImmutableECDSA} from "src/KernelImmutableECDSA.sol"; +import {LibERC7579} from "solady/accounts/LibERC7579.sol"; +import {LibString} from "solady/utils/LibString.sol"; +import {Install} from "src/types/Structs.sol"; +import {MockFallback} from "./mock/MockFallback.sol"; +import {MockExecutor} from "./mock/MockExecutor.sol"; +import {MockValidator} from "./mock/MockValidator.sol"; +import {MockHook} from "./mock/MockHook.sol"; +import {MockPolicy} from "./mock/MockPolicy.sol"; +import {MockSigner} from "./mock/MockSigner.sol"; +import {MockERC721} from "./mock/MockERC721.sol"; +import {MockERC1155} from "./mock/MockERC1155.sol"; +import {MockKernel} from "./mock/MockKernel.sol"; +import {MockCallee} from "./mock/MockCallee.sol"; +import {MockContractETH} from "./mock/MockContractETH.sol"; +import {IHook, IValidator} from "src/interfaces/IERC7579Modules.sol"; +import {CallType} from "src/types/Types.sol"; +import "src/types/Constants.sol"; +import "forge-std/console.sol"; +import "src/types/Error.sol"; +import "src/types/Events.sol"; +import "src/types/Structs.sol"; +import {KernelTestBase} from "./KernelTestBase.sol"; + +contract KernelFactoryTest is KernelTestBase { + function setUp() external { + ep = EntryPointLib.deploy(); + + KernelUUPS uups = new KernelUUPS(ep); + KernelImmutableECDSA immutableECDSA = new KernelImmutableECDSA(ep); + factory = new KernelFactory(uups, immutableECDSA); + helper = new KernelHelper(); + newValidator = new MockValidator(); + callee = new MockCallee(); + executor = makeAddr("Executor"); + mockFallback = new MockFallback(); + beneficiary = payable(makeAddr("Beneficiary")); + policy = new MockPolicy(); + signer = new MockSigner(); + permissionId = bytes20(keccak256(abi.encodePacked("Hello world"))); + vm.txGasPrice(1); + _initialize(); + } + + function _initialize() internal virtual override { + rootValidator = new MockValidator(); + rootValidatorData = hex""; + Install[] memory pkgs = new Install[](1); + pkgs[0] = Install({moduleType: 1, module: address(rootValidator), moduleData: hex"", internalData: hex""}); + kernel = factory.deploy(pkgs, 0); + vm.deal(address(kernel), 1e18); + + vm.startPrank(address(ep)); + kernel.installModule(2, executor, abi.encode(hex"", "")); + vm.stopPrank(); + } + + function test_deploy_root_validator() external unitTest { + vm.skip(is7702); + Install[] memory pkgs = new Install[](1); + pkgs[0] = + Install({moduleType: 1, module: address(rootValidator), moduleData: rootValidatorData, internalData: hex""}); + vm.startSnapshotGas("Mock - deploy()"); + Kernel k = factory.deploy(pkgs, 1); + vm.stopSnapshotGas(); + } + + function test_deploy_root_permission() external unitTest { + Install[] memory pkgs = new Install[](2); + pkgs[0] = Install({ + moduleType: 5, + module: address(policy), + internalData: abi.encodePacked(permissionId), + moduleData: hex"" + }); + pkgs[1] = Install({moduleType: 1, module: address(newValidator), internalData: hex"", moduleData: hex""}); + Kernel k = factory.deploy(pkgs, 1); + assertEq(k.accountId(), "kernel.v0.4"); + assertEq(k.registry(), address(0)); + } + + function test_deploy_root_fail_invalid_root() external unitTest { + Install[] memory pkgs = new Install[](2); + pkgs[0] = Install({moduleType: 2, module: address(executor), internalData: hex"", moduleData: hex""}); + pkgs[1] = Install({moduleType: 1, module: address(newValidator), internalData: hex"", moduleData: hex""}); + vm.expectRevert(InvalidRootValidation.selector); + Kernel k = factory.deploy(pkgs, 1); + } + + function test_deploy_existing() external { + vm.skip(is7702); + Install[] memory pkgs = new Install[](1); + pkgs[0] = + Install({moduleType: 1, module: address(rootValidator), moduleData: rootValidatorData, internalData: hex""}); + Kernel k = factory.deploy(pkgs, 1); + assertEq(address(k), address(factory.deploy(pkgs, 1))); + } + + function test_deploy_with_call() external unitTest { + vm.skip(is7702); + Install[] memory initPkgs = new Install[](1); + initPkgs[0] = + Install({moduleType: 1, module: address(rootValidator), moduleData: rootValidatorData, internalData: hex""}); + Install[] memory pkgs = new Install[](1); + pkgs[0] = Install({moduleType: 1, module: address(newValidator), moduleData: hex"", internalData: hex""}); + kernel = Kernel(payable(factory.getAddress(initPkgs, 1))); + bytes memory sig = enableSig(0, true, false, pkgs, _rootSignHash); + Kernel k = factory.deployWithCall(initPkgs, 1, abi.encodeWithSelector(0xa706cd33, false, 0, pkgs, sig)); + assertEq(address(k), address(kernel)); + ValidationInfo memory vInfo = k.validationInfo(ValidationId.wrap(bytes20(address(newValidator)))); + assertTrue(vInfo.vType == VALIDATION_TYPE_VALIDATOR); + } +} diff --git a/test/KernelHookTest.sol b/test/KernelHookTest.sol new file mode 100644 index 00000000..2452021e --- /dev/null +++ b/test/KernelHookTest.sol @@ -0,0 +1,49 @@ +pragma solidity ^0.8.0; + +import {Test} from "forge-std/Test.sol"; +import {EntryPointLib} from "./utils/EntryPointLib.sol"; +import {IEntryPoint} from "account-abstraction/interfaces/IEntryPoint.sol"; +import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; +import {Kernel} from "src/Kernel.sol"; +import {KernelUUPS} from "src/KernelUUPS.sol"; +import {KernelHelper} from "src/KernelHelper.sol"; +import {SelectorManager} from "src/core/SelectorManager.sol"; +import {KernelFactory} from "src/KernelFactory.sol"; +import {KernelUUPS} from "src/KernelUUPS.sol"; +import {KernelImmutableECDSA} from "src/KernelImmutableECDSA.sol"; +import {LibERC7579} from "solady/accounts/LibERC7579.sol"; +import {LibString} from "solady/utils/LibString.sol"; +import {Install} from "src/types/Structs.sol"; +import {MockFallback} from "./mock/MockFallback.sol"; +import {MockExecutor} from "./mock/MockExecutor.sol"; +import {MockValidator} from "./mock/MockValidator.sol"; +import {MockHook} from "./mock/MockHook.sol"; +import {MockPolicy} from "./mock/MockPolicy.sol"; +import {MockSigner} from "./mock/MockSigner.sol"; +import {MockERC721} from "./mock/MockERC721.sol"; +import {MockERC1155} from "./mock/MockERC1155.sol"; +import {MockCallee} from "./mock/MockCallee.sol"; +import {MockKernel} from "./mock/MockKernel.sol"; +import {IHook, IValidator} from "src/interfaces/IERC7579Modules.sol"; +import {CallType} from "src/types/Types.sol"; +import "src/types/Constants.sol"; +import "forge-std/console.sol"; +import "src/types/Error.sol"; +import "src/types/Events.sol"; +import "src/types/Structs.sol"; +import {KernelTestBase} from "./KernelTestBase.sol"; + +abstract contract KernelHookTest is KernelTestBase { + function test_install_hook() external unitTest { + assertTrue(kernel.supportsModule(4)); + MockHook mockHook = new MockHook(); + kernel.installModule(4, address(mockHook), abi.encode(hex"", "")); + assertTrue(kernel.isModuleInstalled(4, address(mockHook), hex"")); + } + + function test_uninstall_hook() external unitTest { + MockHook mockHook = new MockHook(); + kernel.installModule(4, address(mockHook), abi.encode(hex"", "")); + kernel.uninstallModule(4, address(mockHook), abi.encode(hex"", "")); + } +} diff --git a/test/KernelSelectorTest.sol b/test/KernelSelectorTest.sol new file mode 100644 index 00000000..9b0e7a0a --- /dev/null +++ b/test/KernelSelectorTest.sol @@ -0,0 +1,153 @@ +pragma solidity ^0.8.0; + +import {Test} from "forge-std/Test.sol"; +import {EntryPointLib} from "./utils/EntryPointLib.sol"; +import {IEntryPoint} from "account-abstraction/interfaces/IEntryPoint.sol"; +import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; +import {Kernel} from "src/Kernel.sol"; +import {KernelUUPS} from "src/KernelUUPS.sol"; +import {KernelHelper} from "src/KernelHelper.sol"; +import {SelectorManager} from "src/core/SelectorManager.sol"; +import {KernelFactory} from "src/KernelFactory.sol"; +import {KernelUUPS} from "src/KernelUUPS.sol"; +import {KernelImmutableECDSA} from "src/KernelImmutableECDSA.sol"; +import {LibERC7579} from "solady/accounts/LibERC7579.sol"; +import {LibString} from "solady/utils/LibString.sol"; +import {Install} from "src/types/Structs.sol"; +import {MockFallback} from "./mock/MockFallback.sol"; +import {MockExecutor} from "./mock/MockExecutor.sol"; +import {MockValidator} from "./mock/MockValidator.sol"; +import {MockHook} from "./mock/MockHook.sol"; +import {MockPolicy} from "./mock/MockPolicy.sol"; +import {MockSigner} from "./mock/MockSigner.sol"; +import {MockERC721} from "./mock/MockERC721.sol"; +import {MockERC1155} from "./mock/MockERC1155.sol"; +import {MockCallee} from "./mock/MockCallee.sol"; +import {MockKernel} from "./mock/MockKernel.sol"; +import {IHook, IValidator} from "src/interfaces/IERC7579Modules.sol"; +import {CallType} from "src/types/Types.sol"; +import "src/types/Constants.sol"; +import "forge-std/console.sol"; +import "src/types/Error.sol"; +import "src/types/Events.sol"; +import "src/types/Structs.sol"; +import {KernelTestBase} from "./KernelTestBase.sol"; + +abstract contract KernelSelectorTest is KernelTestBase { + function test_install_selector_call() external unitTest { + assertTrue(kernel.supportsModule(3)); + kernel.installModule( + 3, + address(mockFallback), + abi.encode( + hex"deadbeef", abi.encodePacked(MockFallback.fallbackFunction.selector, bytes1(0x00), address(1)) + ) + ); + vm.expectEmit(address(mockFallback)); + emit MockFallback.Foobar(); + uint256 res = MockFallback(address(kernel)).fallbackFunction(10); + assertEq(res, 100); + SelectorManager.SelectorConfig memory c = kernel.selectorConfig(MockFallback.fallbackFunction.selector); + assertEq(address(c.target), address(mockFallback)); + assertEq(address(c.hook), address(1)); + assertTrue(c.callType == CallType.wrap(bytes1(0x00))); + assertTrue( + kernel.isModuleInstalled(3, address(mockFallback), abi.encodePacked(MockFallback.fallbackFunction.selector)) + ); + } + + function test_install_selector_call_withhook() external unitTest { + MockHook mockHook = new MockHook(); + kernel.installModule(4, address(mockHook), abi.encode(hex"", "")); + kernel.installModule( + 3, + address(mockFallback), + abi.encode( + hex"deadbeef", abi.encodePacked(MockFallback.fallbackFunction.selector, bytes1(0x00), address(mockHook)) + ) + ); + vm.expectEmit(address(mockFallback)); + emit MockFallback.Foobar(); + uint256 res = MockFallback(address(kernel)).fallbackFunction(10); + assertEq(res, 100); + SelectorManager.SelectorConfig memory c = kernel.selectorConfig(MockFallback.fallbackFunction.selector); + assertEq(address(c.target), address(mockFallback)); + assertEq(address(c.hook), address(mockHook)); + assertTrue(c.callType == CallType.wrap(bytes1(0x00))); + } + + function test_uninstall_selector_call() external unitTest { + kernel.installModule( + 3, + address(mockFallback), + abi.encode( + hex"deadbeef", abi.encodePacked(MockFallback.fallbackFunction.selector, bytes1(0x00), address(1)) + ) + ); + vm.expectEmit(address(mockFallback)); + emit MockFallback.Foobar(); + uint256 res = MockFallback(address(kernel)).fallbackFunction(10); + assertEq(res, 100); + SelectorManager.SelectorConfig memory c = kernel.selectorConfig(MockFallback.fallbackFunction.selector); + assertEq(address(c.target), address(mockFallback)); + assertEq(address(c.hook), address(1)); + assertTrue(c.callType == CallType.wrap(bytes1(0x00))); + kernel.uninstallModule( + 3, address(mockFallback), abi.encode(hex"", abi.encodePacked(MockFallback.fallbackFunction.selector)) + ); + c = kernel.selectorConfig(MockFallback.fallbackFunction.selector); + assertEq(address(c.target), address(0)); + assertEq(address(c.hook), address(0)); + assertTrue(c.callType == CallType.wrap(bytes1(0x00))); + } + + function test_install_selector_call_fail() external unitTest { + kernel.installModule( + 3, + address(mockFallback), + abi.encode( + hex"deadbeef", abi.encodePacked(MockFallback.fallbackFunction.selector, bytes1(0x00), address(1)) + ) + ); + vm.expectRevert(MockFallback.Limit.selector, address(mockFallback)); + MockFallback(address(kernel)).fallbackFunction(100); + } + + function test_install_selector_delegatecall() external unitTest { + kernel.installModule( + 3, + address(mockFallback), + abi.encode( + hex"deadbeef", abi.encodePacked(MockFallback.fallbackFunction.selector, bytes1(0xff), address(1)) + ) + ); + vm.expectEmit(address(kernel)); + emit MockFallback.Foobar(); + uint256 res = MockFallback(address(kernel)).fallbackFunction(10); + assertEq(res, 100); + } + + function test_install_selector_delegatecall_fail() external unitTest { + kernel.installModule( + 3, + address(mockFallback), + abi.encode( + hex"deadbeef", abi.encodePacked(MockFallback.fallbackFunction.selector, bytes1(0xff), address(1)) + ) + ); + vm.expectRevert(MockFallback.Limit.selector, address(kernel)); + MockFallback(address(kernel)).fallbackFunction(100); + } + + function test_install_selector_invalid_selector() external unitTest { + kernel.installModule( + 3, + address(mockFallback), + abi.encode( + hex"deadbeef", abi.encodePacked(MockFallback.fallbackFunction.selector, bytes1(0xff), address(1)) + ) + ); + vm.expectRevert(InvalidSelector.selector, address(kernel)); + MockFallback(address(kernel)).getData(); + } +} diff --git a/test/KernelTestBase.sol b/test/KernelTestBase.sol index 6f9de463..85f86cd3 100644 --- a/test/KernelTestBase.sol +++ b/test/KernelTestBase.sol @@ -23,6 +23,7 @@ import {MockSigner} from "./mock/MockSigner.sol"; import {MockERC721} from "./mock/MockERC721.sol"; import {MockERC1155} from "./mock/MockERC1155.sol"; import {MockCallee} from "./mock/MockCallee.sol"; +import {MockContractETH} from "./mock/MockContractETH.sol"; import {MockKernel} from "./mock/MockKernel.sol"; import {IHook, IValidator} from "src/interfaces/IERC7579Modules.sol"; import {CallType} from "src/types/Types.sol"; @@ -216,4 +217,84 @@ abstract contract KernelTestBase is Test { uint192 key = uint192(bytes24(abi.encodePacked(uMode, vType, vId, bytes2(0x00)))); return ep.getNonce(address(kernel), key); } + + function test_codesize() external { + vm.skip(true); + address implementation = address(factory.uups()); + console.log("Code size :", implementation.code.length); + require(implementation.code.length <= 24576, "Code too big"); + console.log("space left :", 24576 - implementation.code.length); + } + + function test_receive_eth() external { + address sender = makeAddr("Sender"); + address payable k = payable(address(kernel)); + vm.deal(sender, 1e18); + // if not through kernel, only
call{value} works + vm.startPrank(sender); + vm.expectEmit(k); + emit Received(sender, uint256(1)); + (bool success,) = k.call{value: 1}(hex""); + require(success); + vm.stopPrank(); + + MockContractETH mock = new MockContractETH(); + vm.deal(address(mock), 1e18); + // if done through kernel, accepts both transfer and send + vm.startPrank(address(ep)); + vm.expectEmit(k); + emit Received(address(mock), uint256(1)); + kernel.execute( + bytes32(0), + abi.encodePacked( + address(mock), uint256(0), abi.encodeWithSelector(MockContractETH.useTransfer.selector, k, uint256(1)) + ) + ); + vm.expectEmit(k); + emit Received(address(mock), uint256(1)); + kernel.execute( + bytes32(0), + abi.encodePacked( + address(mock), uint256(0), abi.encodeWithSelector(MockContractETH.useSend.selector, k, uint256(1)) + ) + ); + vm.stopPrank(); + } + + function test_receive_erc721() external { + MockERC721 mock = new MockERC721(); + address sender = makeAddr("Sender"); + + mock.mint(sender, 1); + + vm.prank(sender); + mock.safeTransferFrom(sender, address(kernel), 1); + + mock.safeMint(address(kernel), 2); + } + + function test_receive_erc1155() external { + MockERC1155 mock = new MockERC1155(); + address sender = makeAddr("Sender"); + + mock.mint(sender, 1, 1, hex"deadbeef"); + vm.prank(sender); + mock.safeTransferFrom(sender, address(kernel), 1, 1, hex"deadbeef"); + + mock.mint(address(kernel), 1, 1, hex"deadbeef"); + + mock.mint(sender, 2, 4, hex"deadbeef"); + mock.mint(sender, 3, 5, hex"deadbeef"); + uint256[] memory ids = new uint256[](2); + ids[0] = 2; + ids[1] = 3; + + uint256[] memory amounts = new uint256[](2); + amounts[0] = 2; + amounts[1] = 3; + vm.prank(sender); + mock.safeBatchTransferFrom(sender, address(kernel), ids, amounts, hex"deadbeef"); + + mock.batchMint(address(kernel), ids, amounts, hex"deadbeef"); + } } diff --git a/test/KernelUserOpTest.sol b/test/KernelUserOpTest.sol new file mode 100644 index 00000000..24bde7f3 --- /dev/null +++ b/test/KernelUserOpTest.sol @@ -0,0 +1,323 @@ +pragma solidity ^0.8.0; + +import {Test} from "forge-std/Test.sol"; +import {EntryPointLib} from "./utils/EntryPointLib.sol"; +import {IEntryPoint} from "account-abstraction/interfaces/IEntryPoint.sol"; +import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; +import {Kernel} from "src/Kernel.sol"; +import {KernelUUPS} from "src/KernelUUPS.sol"; +import {KernelHelper} from "src/KernelHelper.sol"; +import {SelectorManager} from "src/core/SelectorManager.sol"; +import {KernelFactory} from "src/KernelFactory.sol"; +import {KernelUUPS} from "src/KernelUUPS.sol"; +import {KernelImmutableECDSA} from "src/KernelImmutableECDSA.sol"; +import {LibERC7579} from "solady/accounts/LibERC7579.sol"; +import {LibString} from "solady/utils/LibString.sol"; +import {Install} from "src/types/Structs.sol"; +import {MockFallback} from "./mock/MockFallback.sol"; +import {MockExecutor} from "./mock/MockExecutor.sol"; +import {MockValidator} from "./mock/MockValidator.sol"; +import {MockHook} from "./mock/MockHook.sol"; +import {MockPolicy} from "./mock/MockPolicy.sol"; +import {MockSigner} from "./mock/MockSigner.sol"; +import {MockERC721} from "./mock/MockERC721.sol"; +import {MockERC1155} from "./mock/MockERC1155.sol"; +import {MockCallee} from "./mock/MockCallee.sol"; +import {MockKernel} from "./mock/MockKernel.sol"; +import {IHook, IValidator} from "src/interfaces/IERC7579Modules.sol"; +import {CallType} from "src/types/Types.sol"; +import "src/types/Constants.sol"; +import "forge-std/console.sol"; +import "src/types/Error.sol"; +import "src/types/Events.sol"; +import "src/types/Structs.sol"; +import {KernelTestBase} from "./KernelTestBase.sol"; + +abstract contract KernelUserOpTest is KernelTestBase { + function test_executeuserop_root() external entryPointTest { + PackedUserOperation[] memory ops = new PackedUserOperation[](1); + ops[0] = PackedUserOperation({ + sender: address(kernel), + nonce: encodeNonce(false, false, false, bytes1(0), bytes20(0)), + initCode: hex"", + callData: abi.encodePacked( + Kernel.executeUserOp.selector, + abi.encodeWithSelector( + Kernel.execute.selector, + bytes32(0), + abi.encodePacked(address(callee), uint256(0), MockCallee.foo.selector) + ) + ), + accountGasLimits: bytes32(abi.encodePacked(uint128(1000000), uint128(1000000))), + preVerificationGas: 1000000, + gasFees: bytes32(abi.encodePacked(uint128(1), uint128(1))), + paymasterAndData: hex"", + signature: hex"" + }); + ops[0].signature = _rootSignUserOp(ops[0], true, false); + vm.startPrank(address(ep)); + kernel.executeUserOp(ops[0], keccak256("hello world")); + vm.stopPrank(); + assertEq(callee.bar(), 1); + } + + function test_userop_root() external entryPointTest { + PackedUserOperation[] memory ops = new PackedUserOperation[](1); + ops[0] = PackedUserOperation({ + sender: address(kernel), + nonce: encodeNonce(false, false, false, bytes1(0), bytes20(0)), + initCode: hex"", + callData: abi.encodeWithSelector( + Kernel.execute.selector, bytes32(0), abi.encodePacked(address(callee), uint256(0), MockCallee.foo.selector) + ), + accountGasLimits: bytes32(abi.encodePacked(uint128(1000000), uint128(1000000))), + preVerificationGas: 1000000, + gasFees: bytes32(abi.encodePacked(uint128(1), uint128(1))), + paymasterAndData: hex"", + signature: hex"" + }); + ops[0].signature = _rootSignUserOp(ops[0], true, false); + vm.startSnapshotGas("Root - foo()"); + ep.handleOps(ops, beneficiary); + vm.stopSnapshotGas(); + assertEq(callee.bar(), 1); + } + + function test_userop_root_replayable() external entryPointTest { + PackedUserOperation[] memory ops = new PackedUserOperation[](1); + ops[0] = PackedUserOperation({ + sender: address(kernel), + nonce: encodeNonce(true, false, false, bytes1(0), bytes20(0)), + initCode: hex"", + callData: abi.encodeWithSelector( + Kernel.execute.selector, bytes32(0), abi.encodePacked(address(callee), uint256(0), MockCallee.foo.selector) + ), + accountGasLimits: bytes32(abi.encodePacked(uint128(1000000), uint128(1000000))), + preVerificationGas: 1000000, + gasFees: bytes32(abi.encodePacked(uint128(1), uint128(1))), + paymasterAndData: hex"", + signature: hex"" + }); + ops[0].signature = _rootSignUserOp(ops[0], true, true); + ep.handleOps(ops, beneficiary); + assertEq(callee.bar(), 1); + } + + function test_userop_root_aa24_validation_failed() external entryPointTest { + PackedUserOperation[] memory ops = new PackedUserOperation[](1); + ops[0] = PackedUserOperation({ + sender: address(kernel), + nonce: encodeNonce(false, false, false, bytes1(0x00), bytes20(0)), + initCode: hex"", + callData: abi.encodeWithSelector( + Kernel.execute.selector, bytes32(0), abi.encodePacked(address(callee), uint256(0), MockCallee.foo.selector) + ), + accountGasLimits: bytes32(abi.encodePacked(uint128(1000000), uint128(1000000))), + preVerificationGas: 1000000, + gasFees: bytes32(abi.encodePacked(uint128(1), uint128(1))), + paymasterAndData: hex"", + signature: hex"" + }); + ops[0].signature = _rootSignUserOp(ops[0], false, false); + vm.expectRevert(abi.encodeWithSelector(IEntryPoint.FailedOp.selector, 0, "AA24 signature error")); + ep.handleOps(ops, beneficiary); + } + + function test_userop_validator_aa24_notinstalled() external entryPointTest { + PackedUserOperation[] memory ops = new PackedUserOperation[](1); + ops[0] = PackedUserOperation({ + sender: address(kernel), + nonce: encodeNonce(false, false, false, bytes1(0x01), bytes20(address(newValidator))), + initCode: hex"", + callData: abi.encodeWithSelector( + Kernel.execute.selector, bytes32(0), abi.encodePacked(address(callee), uint256(0), MockCallee.foo.selector) + ), + accountGasLimits: bytes32(abi.encodePacked(uint128(1000000), uint128(1000000))), + preVerificationGas: 1000000, + gasFees: bytes32(abi.encodePacked(uint128(1), uint128(1))), + paymasterAndData: hex"", + signature: hex"" + }); + ops[0].signature = _validatorSignUserOp(ops[0], true, false); + vm.expectRevert(); + ep.handleOps(ops, beneficiary); + } + + function test_userop_validator_enable() external entryPointTest { + PackedUserOperation[] memory ops = new PackedUserOperation[](1); + ops[0] = PackedUserOperation({ + sender: address(kernel), + nonce: encodeNonce(false, true, false, bytes1(0x01), bytes20(address(newValidator))), + initCode: hex"", + callData: abi.encodeWithSelector( + Kernel.execute.selector, bytes32(0), abi.encodePacked(address(callee), uint256(0), MockCallee.foo.selector) + ), + accountGasLimits: bytes32(abi.encodePacked(uint128(1000000), uint128(1000000))), + preVerificationGas: 1000000, + gasFees: bytes32(abi.encodePacked(uint128(1), uint128(1))), + paymasterAndData: hex"", + signature: hex"" + }); + ops[0].signature = encodeEnableValidatorSignature( + Kernel.execute.selector, 0, true, false, _rootSignHash, _validatorSignUserOp(ops[0], true, false) + ); + ep.handleOps(ops, beneficiary); + assertEq(callee.bar(), 1); + } + + function test_userop_validator_aa24_enable_fail_wrong_signature() external entryPointTest { + PackedUserOperation[] memory ops = new PackedUserOperation[](1); + ops[0] = PackedUserOperation({ + sender: address(kernel), + nonce: encodeNonce(false, true, false, bytes1(0x01), bytes20(address(newValidator))), + initCode: hex"", + callData: abi.encodeWithSelector( + Kernel.execute.selector, bytes32(0), abi.encodePacked(address(callee), uint256(0), MockCallee.foo.selector) + ), + accountGasLimits: bytes32(abi.encodePacked(uint128(1000000), uint128(1000000))), + preVerificationGas: 1000000, + gasFees: bytes32(abi.encodePacked(uint128(1), uint128(1))), + paymasterAndData: hex"", + signature: hex"" + }); + ops[0].signature = encodeEnableValidatorSignature( + Kernel.execute.selector, 0, false, false, _rootSignHash, _validatorSignUserOp(ops[0], true, false) + ); + vm.expectRevert(abi.encodeWithSelector(IEntryPoint.FailedOp.selector, 0, "AA24 signature error")); + ep.handleOps(ops, beneficiary); + } + + function test_userop_validator_aa24_validation_failed() external entryPointTest { + PackedUserOperation[] memory ops = new PackedUserOperation[](1); + ops[0] = PackedUserOperation({ + sender: address(kernel), + nonce: encodeNonce(false, true, false, bytes1(0x01), bytes20(address(newValidator))), + initCode: hex"", + callData: abi.encodeWithSelector( + Kernel.execute.selector, bytes32(0), abi.encodePacked(address(callee), uint256(0), MockCallee.foo.selector) + ), + accountGasLimits: bytes32(abi.encodePacked(uint128(1000000), uint128(1000000))), + preVerificationGas: 1000000, + gasFees: bytes32(abi.encodePacked(uint128(1), uint128(1))), + paymasterAndData: hex"", + signature: hex"" + }); + + ops[0].signature = encodeEnableValidatorSignature( + Kernel.execute.selector, 0, true, false, _rootSignHash, _validatorSignUserOp(ops[0], false, false) + ); + vm.expectRevert(abi.encodeWithSelector(IEntryPoint.FailedOp.selector, 0, "AA24 signature error")); + ep.handleOps(ops, beneficiary); + } + + function test_userop_permission_aa24_notinstalled() external entryPointTest { + PackedUserOperation[] memory ops = new PackedUserOperation[](1); + ops[0] = PackedUserOperation({ + sender: address(kernel), + nonce: encodeNonce(false, false, false, bytes1(0x02), permissionId), + initCode: hex"", + callData: abi.encodeWithSelector( + Kernel.execute.selector, bytes32(0), abi.encodePacked(address(callee), uint256(0), MockCallee.foo.selector) + ), + accountGasLimits: bytes32(abi.encodePacked(uint128(1000000), uint128(1000000))), + preVerificationGas: 1000000, + gasFees: bytes32(abi.encodePacked(uint128(1), uint128(1))), + paymasterAndData: hex"", + signature: hex"" + }); + ops[0].signature = _permissionSignUserOp(ops[0], true, false); + //vm.expectRevert(abi.encodeWithSelector(IEntryPoint.FailedOp.selector, 0, "AA24 signature error")); + vm.expectRevert(); + ep.handleOps(ops, beneficiary); + } + + function test_userop_permission_enable() external entryPointTest { + PackedUserOperation[] memory ops = new PackedUserOperation[](1); + ops[0] = PackedUserOperation({ + sender: address(kernel), + nonce: encodeNonce(false, true, false, bytes1(0x02), permissionId), + initCode: hex"", + callData: abi.encodeWithSelector( + Kernel.execute.selector, bytes32(0), abi.encodePacked(address(callee), uint256(0), MockCallee.foo.selector) + ), + accountGasLimits: bytes32(abi.encodePacked(uint128(1000000), uint128(1000000))), + preVerificationGas: 1000000, + gasFees: bytes32(abi.encodePacked(uint128(1), uint128(1))), + paymasterAndData: hex"", + signature: hex"" + }); + + ops[0].signature = encodeEnablePermissionSignature( + Kernel.execute.selector, 0, true, false, _rootSignHash, _permissionSignUserOp(ops[0], true, false) + ); + ep.handleOps(ops, beneficiary); + assertEq(callee.bar(), 1); + } + + function test_userop_permission_aa24_enable_fail_wrong_signature() external entryPointTest { + PackedUserOperation[] memory ops = new PackedUserOperation[](1); + ops[0] = PackedUserOperation({ + sender: address(kernel), + nonce: encodeNonce(false, true, false, bytes1(0x02), permissionId), + initCode: hex"", + callData: abi.encodeWithSelector( + Kernel.execute.selector, bytes32(0), abi.encodePacked(address(callee), uint256(0), MockCallee.foo.selector) + ), + accountGasLimits: bytes32(abi.encodePacked(uint128(1000000), uint128(1000000))), + preVerificationGas: 1000000, + gasFees: bytes32(abi.encodePacked(uint128(1), uint128(1))), + paymasterAndData: hex"", + signature: hex"" + }); + ops[0].signature = encodeEnablePermissionSignature( + Kernel.execute.selector, 0, false, false, _rootSignHash, _permissionSignUserOp(ops[0], true, false) + ); + vm.expectRevert(abi.encodeWithSelector(IEntryPoint.FailedOp.selector, 0, "AA24 signature error")); + ep.handleOps(ops, beneficiary); + } + + function test_userop_permission_aa24_policy_failed() external entryPointTest { + PackedUserOperation[] memory ops = new PackedUserOperation[](1); + ops[0] = PackedUserOperation({ + sender: address(kernel), + nonce: encodeNonce(false, true, false, bytes1(0x02), permissionId), + initCode: hex"", + callData: abi.encodeWithSelector( + Kernel.execute.selector, bytes32(0), abi.encodePacked(address(callee), uint256(0), MockCallee.foo.selector) + ), + accountGasLimits: bytes32(abi.encodePacked(uint128(1000000), uint128(1000000))), + preVerificationGas: 1000000, + gasFees: bytes32(abi.encodePacked(uint128(1), uint128(1))), + paymasterAndData: hex"", + signature: hex"" + }); + ops[0].signature = encodeEnablePermissionSignature( + Kernel.execute.selector, 0, true, false, _rootSignHash, _permissionSignUserOp(ops[0], false, false) + ); + vm.expectRevert(abi.encodeWithSelector(IEntryPoint.FailedOp.selector, 0, "AA24 signature error")); + ep.handleOps(ops, beneficiary); + } + + function test_userop_permission_aa24_signer_validation_failed() external entryPointTest { + PackedUserOperation[] memory ops = new PackedUserOperation[](1); + ops[0] = PackedUserOperation({ + sender: address(kernel), + nonce: encodeNonce(false, true, false, bytes1(0x02), permissionId), + initCode: hex"", + callData: abi.encodeWithSelector( + Kernel.execute.selector, bytes32(0), abi.encodePacked(address(callee), uint256(0), MockCallee.foo.selector) + ), + accountGasLimits: bytes32(abi.encodePacked(uint128(1000000), uint128(1000000))), + preVerificationGas: 1000000, + gasFees: bytes32(abi.encodePacked(uint128(1), uint128(1))), + paymasterAndData: hex"", + signature: hex"" + }); + permissionRevertIndex = 1; + ops[0].signature = encodeEnablePermissionSignature( + Kernel.execute.selector, 0, true, false, _rootSignHash, _permissionSignUserOp(ops[0], false, false) + ); + vm.expectRevert(abi.encodeWithSelector(IEntryPoint.FailedOp.selector, 0, "AA24 signature error")); + ep.handleOps(ops, beneficiary); + } +} diff --git a/test/KernelValidatorTest.sol b/test/KernelValidatorTest.sol new file mode 100644 index 00000000..115d17e2 --- /dev/null +++ b/test/KernelValidatorTest.sol @@ -0,0 +1,193 @@ +pragma solidity ^0.8.0; + +import {Test} from "forge-std/Test.sol"; +import {EntryPointLib} from "./utils/EntryPointLib.sol"; +import {IEntryPoint} from "account-abstraction/interfaces/IEntryPoint.sol"; +import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; +import {Kernel} from "src/Kernel.sol"; +import {KernelUUPS} from "src/KernelUUPS.sol"; +import {KernelHelper} from "src/KernelHelper.sol"; +import {SelectorManager} from "src/core/SelectorManager.sol"; +import {KernelFactory} from "src/KernelFactory.sol"; +import {KernelUUPS} from "src/KernelUUPS.sol"; +import {KernelImmutableECDSA} from "src/KernelImmutableECDSA.sol"; +import {LibERC7579} from "solady/accounts/LibERC7579.sol"; +import {LibString} from "solady/utils/LibString.sol"; +import {Install} from "src/types/Structs.sol"; +import {MockFallback} from "./mock/MockFallback.sol"; +import {MockExecutor} from "./mock/MockExecutor.sol"; +import {MockValidator} from "./mock/MockValidator.sol"; +import {MockHook} from "./mock/MockHook.sol"; +import {MockPolicy} from "./mock/MockPolicy.sol"; +import {MockSigner} from "./mock/MockSigner.sol"; +import {MockERC721} from "./mock/MockERC721.sol"; +import {MockERC1155} from "./mock/MockERC1155.sol"; +import {MockCallee} from "./mock/MockCallee.sol"; +import {MockKernel} from "./mock/MockKernel.sol"; +import {IHook, IValidator} from "src/interfaces/IERC7579Modules.sol"; +import {CallType} from "src/types/Types.sol"; +import "src/types/Constants.sol"; +import "forge-std/console.sol"; +import "src/types/Error.sol"; +import "src/types/Events.sol"; +import "src/types/Structs.sol"; +import {KernelTestBase} from "./KernelTestBase.sol"; + +abstract contract KernelValidatorTest is KernelTestBase { + function test_set_valid_nonce() external unitTest { + kernel.setValidNonceFrom(1); + assertEq(kernel.validNonceFrom(), 1); + + Install[] memory packages = new Install[](2); + packages[0] = Install({moduleType: 1, module: address(newValidator), internalData: hex"", moduleData: hex""}); + packages[1] = Install({ + moduleType: 5, + module: address(policy), + internalData: abi.encodePacked(permissionId), + moduleData: hex"" + }); + bytes memory sig = enableSig(0, true, false, packages, _rootSignHash); + vm.expectRevert(InvalidNonce.selector); + kernel.installModule(false, 0, packages, sig); + sig = enableSig(uint256(1) << 64, true, false, packages, _rootSignHash); + vm.expectRevert(InvalidNonce.selector); + kernel.installModule(false, uint256(1) << 64, packages, sig); + sig = enableSig(1, true, false, packages, _rootSignHash); + kernel.installModule(false, 1, packages, sig); + } + + function test_set_nonce() external unitTest { + kernel.setNonce(0, 1); + assertEq(kernel.nonce(0), 1); + + Install[] memory packages = new Install[](2); + packages[0] = Install({moduleType: 1, module: address(newValidator), internalData: hex"", moduleData: hex""}); + packages[1] = Install({ + moduleType: 5, + module: address(policy), + internalData: abi.encodePacked(permissionId), + moduleData: hex"" + }); + bytes memory sig = enableSig(0, true, false, packages, _rootSignHash); + vm.expectRevert(InvalidNonce.selector); + kernel.installModule(false, 0, packages, sig); + sig = enableSig(uint256(1) << 64, true, false, packages, _rootSignHash); + kernel.installModule(false, uint256(1) << 64, packages, sig); + } + + function test_set_valid_nonce_decrease_nonce() external unitTest { + kernel.setValidNonceFrom(100); + assertEq(kernel.validNonceFrom(), 100); + assertEq(kernel.nonce(0), 100); + vm.expectRevert(InvalidNonce.selector); + kernel.setValidNonceFrom(1); + } + + function test_change_root() external unitTest { + Install[] memory packages = new Install[](2); + packages[0] = Install({moduleType: 1, module: address(newValidator), internalData: hex"", moduleData: hex""}); + packages[1] = Install({ + moduleType: 5, + module: address(policy), + internalData: abi.encodePacked(permissionId), + moduleData: hex"" + }); + kernel.installModule(false, 0, packages, enableSig(0, true, false, packages, _rootSignHash)); + + kernel.setRoot(ValidationId.wrap(bytes20(address(newValidator)))); + } + + function test_install_validator() external unitTest { + assertTrue(kernel.supportsModule(1)); + ValidationId vId = ValidationId.wrap(bytes20(address(newValidator))); + kernel.installModule(1, address(newValidator), abi.encode(hex"deadbeef", hex"")); + ValidationInfo memory vInfo = kernel.validationInfo(vId); + assertTrue(vInfo.vType == VALIDATION_TYPE_VALIDATOR); + bytes4 ret = kernel.isValidSignature( + keccak256("Hello world"), abi.encodePacked(newValidator, _validatorSignHash(keccak256("Hello world"), true)) + ); + assertEq(ret, ERC1271_MAGICVALUE); + assertTrue(kernel.isModuleInstalled(1, address(newValidator), hex"")); + } + + function test_uninstall_validator() external unitTest { + ValidationId vId = ValidationId.wrap(bytes20(address(newValidator))); + kernel.installModule(1, address(newValidator), abi.encode(hex"deadbeef", hex"")); + ValidationInfo memory vInfo = kernel.validationInfo(vId); + assertTrue(vInfo.vType == VALIDATION_TYPE_VALIDATOR); + kernel.uninstallModule(1, address(newValidator), abi.encode(hex"deadbeef", hex"")); + vInfo = kernel.validationInfo(vId); + assertTrue(vInfo.vType == VALIDATION_TYPE_ROOT); + } + + function test_install_permission() external unitTest { + assertTrue(kernel.supportsModule(5)); + assertTrue(kernel.supportsModule(6)); + ValidationId vId = ValidationId.wrap(permissionId); + ValidationInfo memory vInfo = kernel.validationInfo(vId); + assertTrue(vInfo.vType == VALIDATION_TYPE_ROOT); + assertFalse(kernel.isModuleInstalled(5, address(policy), abi.encodePacked(permissionId))); + assertFalse(kernel.isModuleInstalled(6, address(signer), abi.encodePacked(permissionId))); + kernel.installModule(5, address(policy), abi.encode(hex"deadbeef", abi.encodePacked(permissionId))); + kernel.installModule(6, address(signer), abi.encode(hex"deadbeef", abi.encodePacked(permissionId))); + bytes4 ret = kernel.isValidSignature( + keccak256("Hello world"), + abi.encodePacked(permissionId, _permissionSignHash(keccak256("Hello world"), true)) + ); + assertEq(ret, ERC1271_MAGICVALUE); + assertTrue(kernel.isModuleInstalled(5, address(policy), abi.encodePacked(permissionId))); + assertTrue(kernel.isModuleInstalled(6, address(signer), abi.encodePacked(permissionId))); + } + + function test_install_policy() external unitTest { + assertTrue(kernel.supportsModule(5)); + MockPolicy mock = new MockPolicy(); + ValidationId vId = ValidationId.wrap(permissionId); + ValidationInfo memory vInfo = kernel.validationInfo(vId); + assertTrue(vInfo.vType == VALIDATION_TYPE_ROOT); + kernel.installModule(5, address(mock), abi.encode(hex"deadbeef", abi.encodePacked(vId))); + vInfo = kernel.validationInfo(vId); + assertTrue(vInfo.vType == VALIDATION_TYPE_PERMISSION); + assertTrue(kernel.isModuleInstalled(5, address(mock), abi.encodePacked(permissionId))); + } + + function test_uninstall_policy() external unitTest { + MockPolicy mock = new MockPolicy(); + ValidationId vId = ValidationId.wrap(permissionId); + ValidationInfo memory vInfo = kernel.validationInfo(vId); + assertTrue(vInfo.vType == VALIDATION_TYPE_ROOT); + kernel.installModule(5, address(mock), abi.encode(hex"deadbeef", abi.encodePacked(vId))); + vInfo = kernel.validationInfo(vId); + assertTrue(vInfo.vType == VALIDATION_TYPE_PERMISSION); + kernel.uninstallModule(5, address(mock), abi.encode(hex"deadbeef", abi.encodePacked(vId))); + vInfo = kernel.validationInfo(vId); + assertTrue(vInfo.vType == VALIDATION_TYPE_ROOT); + } + + function test_install_signer() external unitTest { + assertTrue(kernel.supportsModule(6)); + MockSigner mock = new MockSigner(); + ValidationId vId = ValidationId.wrap(permissionId); + ValidationInfo memory vInfo = kernel.validationInfo(vId); + assertTrue(vInfo.vType == VALIDATION_TYPE_ROOT); + kernel.installModule(6, address(mock), abi.encode(hex"deadbeef", abi.encodePacked(vId))); + vInfo = kernel.validationInfo(vId); + assertTrue(vInfo.vType == VALIDATION_TYPE_PERMISSION); + assertTrue(kernel.isModuleInstalled(6, address(mock), abi.encodePacked(permissionId))); + } + + function test_uninstall_signer() external unitTest { + MockSigner mock = new MockSigner(); + ValidationId vId = ValidationId.wrap(bytes20(keccak256(abi.encodePacked("deadbeef")))); + ValidationInfo memory vInfo = kernel.validationInfo(vId); + assertTrue(vInfo.vType == VALIDATION_TYPE_ROOT); + kernel.installModule(6, address(mock), abi.encode(hex"deadbeef", abi.encodePacked(vId))); + vInfo = kernel.validationInfo(vId); + assertTrue(vInfo.vType == VALIDATION_TYPE_PERMISSION); + assertTrue(vInfo.signer == address(mock)); + kernel.uninstallModule(6, address(mock), abi.encode(hex"deadbeef", abi.encodePacked(vId))); + vInfo = kernel.validationInfo(vId); + assertTrue(vInfo.vType == VALIDATION_TYPE_ROOT); + assertTrue(vInfo.signer == address(0)); + } +} From 077af4780a18b4c7b7a2fc8ca6738d92fa08fb9f Mon Sep 17 00:00:00 2001 From: leekt Date: Thu, 25 Sep 2025 14:03:27 +0900 Subject: [PATCH 056/121] lint --- snapshots/KernelECDSATest.json | 1 - snapshots/KernelFactoryTest.json | 3 ++ snapshots/KernelImmutableECDSATest.json | 3 +- snapshots/KernelTest.json | 1 - src/Kernel.sol | 23 +++++----- src/KernelFactory.sol | 26 +++++------ src/KernelHelper.sol | 5 +-- src/KernelImmutableECDSA.sol | 1 - src/core/ExecutionManager.sol | 2 +- src/core/ExecutorManager.sol | 5 +-- src/core/HookManager.sol | 12 ++---- src/core/ModuleManager.sol | 16 +++---- src/core/SelectorManager.sol | 8 ++-- src/core/ValidationManager.sol | 10 ++--- src/interfaces/IERC7579Account.sol | 2 - src/lib/ERC1271.sol | 4 +- src/lib/Lib4337.sol | 2 - src/types/Constants.sol | 2 +- src/types/Structs.sol | 2 +- test/Kernel.t.sol | 26 +++-------- test/Kernel7702.t.sol | 4 +- test/KernelECDSA.t.sol | 8 ++-- test/KernelERC1271Test.sol | 57 ++++++------------------- test/KernelExecuteTest.sol | 31 +------------- test/KernelExecutorTest.sol | 29 +------------ test/KernelFactory.t.sol | 28 +++--------- test/KernelHookTest.sol | 30 ------------- test/KernelImmutableECDSA.t.sol | 7 ++- test/KernelSelectorTest.sol | 28 +----------- test/KernelTestBase.sol | 23 +++------- test/KernelUserOpTest.sol | 27 ------------ test/KernelValidatorTest.sol | 38 ++++------------- test/mock/ECDSAValidator.sol | 7 +-- test/mock/MockERC1155.sol | 2 +- test/mock/MockERC20.sol | 4 +- test/mock/MockERC721.sol | 6 +-- test/mock/MockFallback.sol | 1 - test/mock/MockKernel.sol | 4 +- test/mock/MockPolicy.sol | 1 - test/mock/MockSigner.sol | 3 +- test/mock/MockValidator.sol | 7 +-- 41 files changed, 131 insertions(+), 368 deletions(-) create mode 100644 snapshots/KernelFactoryTest.json diff --git a/snapshots/KernelECDSATest.json b/snapshots/KernelECDSATest.json index e3b1a328..df696f33 100644 --- a/snapshots/KernelECDSATest.json +++ b/snapshots/KernelECDSATest.json @@ -1,4 +1,3 @@ { - "Mock - deploy()": "158293", "Root - foo()": "180217" } \ No newline at end of file diff --git a/snapshots/KernelFactoryTest.json b/snapshots/KernelFactoryTest.json new file mode 100644 index 00000000..5f524074 --- /dev/null +++ b/snapshots/KernelFactoryTest.json @@ -0,0 +1,3 @@ +{ + "Mock - deploy()": "159102" +} \ No newline at end of file diff --git a/snapshots/KernelImmutableECDSATest.json b/snapshots/KernelImmutableECDSATest.json index 723d5d9e..ea876918 100644 --- a/snapshots/KernelImmutableECDSATest.json +++ b/snapshots/KernelImmutableECDSATest.json @@ -1,4 +1,3 @@ { - "Mock - deploy()": "158293", - "Root - foo()": "169103" + "Root - foo()": "171565" } \ No newline at end of file diff --git a/snapshots/KernelTest.json b/snapshots/KernelTest.json index 993bba0e..2f7500b9 100644 --- a/snapshots/KernelTest.json +++ b/snapshots/KernelTest.json @@ -1,4 +1,3 @@ { - "Mock - deploy()": "159102", "Root - foo()": "194083" } \ No newline at end of file diff --git a/src/Kernel.sol b/src/Kernel.sol index dc248e87..b66beb59 100644 --- a/src/Kernel.sol +++ b/src/Kernel.sol @@ -1,29 +1,28 @@ pragma solidity ^0.8.0; import {IEntryPoint} from "account-abstraction/interfaces/IEntryPoint.sol"; -import {IAccount} from "account-abstraction/interfaces/IAccount.sol"; import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; -import {IValidator, IExecutor, IHook} from "./interfaces/IERC7579Modules.sol"; +import {IExecutor, IHook} from "./interfaces/IERC7579Modules.sol"; import {ModuleManager, Install} from "./core/ModuleManager.sol"; import {parseNonce} from "./core/ValidationManager.sol"; import {ExecutionManager} from "./core/ExecutionManager.sol"; import {Lib4337} from "./lib/Lib4337.sol"; import {LibERC7579} from "solady/accounts/LibERC7579.sol"; -import "./types/Types.sol"; -import "./types/Error.sol"; -import "./types/Events.sol"; -import "./types/Constants.sol"; -import "./types/Structs.sol"; +import {CallType, ValidationId, ValidationMode, ValidationType, isEnable, isReplayable, isEnableReplayable} from "./types/Types.sol"; +import {NotImplemented,Unauthorized,UnauthorizedCallData, InvalidSelector, InvalidInitialization, InstallSignatureVerificationFailed} from "./types/Error.sol"; +import {Received} from "./types/Events.sol"; +import {VALIDATION_TYPE_ROOT} from "./types/Constants.sol"; +import {ValidationStorage, ValidationInfo} from "./types/Structs.sol"; abstract contract Kernel is ModuleManager, ExecutionManager { - IEntryPoint immutable entryPoint; + IEntryPoint immutable ENTRYPOINT; function _onlyEntryPointOrSelf() internal { - require(msg.sender == address(entryPoint) || msg.sender == address(this), Unauthorized()); + require(msg.sender == address(ENTRYPOINT) || msg.sender == address(this), Unauthorized()); } - constructor(IEntryPoint _entryPoint) { - entryPoint = _entryPoint; + constructor(IEntryPoint _entrypoint) { + ENTRYPOINT = _entrypoint; } function _domainNameAndVersion() internal pure override returns (string memory name, string memory version) { @@ -158,7 +157,7 @@ abstract contract Kernel is ModuleManager, ExecutionManager { SelectorConfig storage $ = _selectorConfig(selector); // if the selector is not initialized, revert // if the selector is installed but hook is not set, only entrypoint can call it - if ($.target == address(0) || ($.hook == IHook(address(0)) && msg.sender != address(entryPoint))) { + if ($.target == address(0) || ($.hook == IHook(address(0)) && msg.sender != address(ENTRYPOINT))) { revert InvalidSelector(); } bytes memory hookData; diff --git a/src/KernelFactory.sol b/src/KernelFactory.sol index 5df4a528..532d0b6d 100644 --- a/src/KernelFactory.sol +++ b/src/KernelFactory.sol @@ -4,15 +4,14 @@ import {Kernel, Install} from "./Kernel.sol"; import {KernelUUPS} from "./KernelUUPS.sol"; import {KernelImmutableECDSA} from "./KernelImmutableECDSA.sol"; import {LibClone} from "solady/utils/LibClone.sol"; -import {IEntryPoint} from "account-abstraction/interfaces/IEntryPoint.sol"; contract KernelFactory { - KernelUUPS public immutable uups; - KernelImmutableECDSA public immutable immutableECDSA; + KernelUUPS public immutable UUPS; + KernelImmutableECDSA public immutable IMMUTABLE_ECDSA; - constructor(KernelUUPS _uups, KernelImmutableECDSA _immutableECDSA) { - uups = _uups; - immutableECDSA = _immutableECDSA; + constructor(KernelUUPS _uups, KernelImmutableECDSA _immutableEcdsa) { + UUPS = _uups; + IMMUTABLE_ECDSA = _immutableEcdsa; } function checkInitialized(address account, bytes calldata initData) external view returns (bool) { @@ -39,7 +38,7 @@ contract KernelFactory { // Kernel UUPS function deploy(Install[] calldata initialPackages, uint256 nonce) external payable returns (Kernel) { bytes32 salt = keccak256(abi.encode(initialPackages, nonce)); - (bool deployed, address account) = LibClone.createDeterministicERC1967(msg.value, address(uups), salt); + (bool deployed, address account) = LibClone.createDeterministicERC1967(msg.value, address(UUPS), salt); Kernel k = Kernel(payable(account)); if (deployed) { return k; @@ -54,7 +53,7 @@ contract KernelFactory { returns (Kernel) { bytes32 salt = keccak256(abi.encode(initialPackages, nonce)); - (bool deployed, address account) = LibClone.createDeterministicERC1967(msg.value, address(uups), salt); + (bool deployed, address account) = LibClone.createDeterministicERC1967(msg.value, address(UUPS), salt); Kernel k = Kernel(payable(account)); if (!deployed) { k.initialize(initialPackages); @@ -66,10 +65,11 @@ contract KernelFactory { function getAddress(Install[] calldata initialPackages, uint256 nonce) public view virtual returns (address) { bytes32 salt = keccak256(abi.encode(initialPackages, nonce)); - return LibClone.predictDeterministicAddressERC1967(address(uups), salt, address(this)); + return LibClone.predictDeterministicAddressERC1967(address(UUPS), salt, address(this)); } // Kernel UUPS ECDSA fallback + /// forge-lint: disable-next-line(mixed-case-function) function deployECDSA(address signer, Install[] calldata initialPackages, uint256 nonce) external payable @@ -77,12 +77,13 @@ contract KernelFactory { { bytes32 salt = keccak256(abi.encode(initialPackages, nonce)); (, address account) = - LibClone.createDeterministicERC1967(address(immutableECDSA), abi.encodePacked(signer), salt); + LibClone.createDeterministicERC1967(address(IMMUTABLE_ECDSA), abi.encodePacked(signer), salt); Kernel k = Kernel(payable(account)); k.initialize(initialPackages); return k; } + /// forge-lint: disable-next-line(mixed-case-function) function deployECDSAWithCall( address signer, Install[] calldata initialPackages, @@ -91,7 +92,7 @@ contract KernelFactory { ) external payable returns (Kernel) { bytes32 salt = keccak256(abi.encode(initialPackages, nonce)); (, address account) = - LibClone.createDeterministicERC1967(address(immutableECDSA), abi.encodePacked(signer), salt); + LibClone.createDeterministicERC1967(address(IMMUTABLE_ECDSA), abi.encodePacked(signer), salt); Kernel k = Kernel(payable(account)); k.initialize(initialPackages); (bool success,) = address(k).call(extraCall); @@ -99,6 +100,7 @@ contract KernelFactory { return k; } + /// forge-lint: disable-next-line(mixed-case-function) function getECDSAAddress(address signer, Install[] calldata initialPackages, uint256 nonce) public view @@ -107,7 +109,7 @@ contract KernelFactory { { bytes32 salt = keccak256(abi.encode(initialPackages, nonce)); return LibClone.predictDeterministicAddressERC1967( - address(immutableECDSA), abi.encodePacked(signer), salt, address(this) + address(IMMUTABLE_ECDSA), abi.encodePacked(signer), salt, address(this) ); } } diff --git a/src/KernelHelper.sol b/src/KernelHelper.sol index 677e703d..3cfd49d9 100644 --- a/src/KernelHelper.sol +++ b/src/KernelHelper.sol @@ -1,8 +1,7 @@ pragma solidity ^0.8.0; -import "./types/Structs.sol"; -import {IERC5267} from "./interfaces/IERC5267.sol"; -import "./lib/Utils.sol"; +import {calldataKeccak} from "./lib/Utils.sol"; +import {Install, Call, InstallAndExecute} from "./types/Structs.sol"; contract KernelHelper { /// @dev `keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)")`. diff --git a/src/KernelImmutableECDSA.sol b/src/KernelImmutableECDSA.sol index 925f9879..aa397a8c 100644 --- a/src/KernelImmutableECDSA.sol +++ b/src/KernelImmutableECDSA.sol @@ -1,7 +1,6 @@ pragma solidity ^0.8.0; import {IEntryPoint} from "account-abstraction/interfaces/IEntryPoint.sol"; -import {Kernel} from "./Kernel.sol"; import {KernelUUPS} from "./KernelUUPS.sol"; import {ECDSA} from "solady/utils/ECDSA.sol"; import {LibClone} from "solady/utils/LibClone.sol"; diff --git a/src/core/ExecutionManager.sol b/src/core/ExecutionManager.sol index 73116b0c..ef85c4d4 100644 --- a/src/core/ExecutionManager.sol +++ b/src/core/ExecutionManager.sol @@ -1,7 +1,7 @@ pragma solidity ^0.8.0; import {LibERC7579} from "solady/accounts/LibERC7579.sol"; -import "../types/Error.sol"; +import {InvalidExecType, InvalidCallType} from "../types/Error.sol"; abstract contract ExecutionManager { function _execute(bytes32 mode, bytes calldata executionData) internal { diff --git a/src/core/ExecutorManager.sol b/src/core/ExecutorManager.sol index ee0e55b2..9446fce2 100644 --- a/src/core/ExecutorManager.sol +++ b/src/core/ExecutorManager.sol @@ -1,8 +1,7 @@ pragma solidity ^0.8.0; -import "../types/Types.sol"; -import "../types/Constants.sol"; -import "../interfaces/IERC7579Modules.sol"; +import {EXECUTOR_MANAGER_STORAGE_SLOT} from "../types/Constants.sol"; +import {IExecutor, IHook} from "../interfaces/IERC7579Modules.sol"; contract ExecutorManager { error NotExecutor(); diff --git a/src/core/HookManager.sol b/src/core/HookManager.sol index 0b6b04b9..886fc6f6 100644 --- a/src/core/HookManager.sol +++ b/src/core/HookManager.sol @@ -1,14 +1,8 @@ pragma solidity ^0.8.0; -import {IHook, IFallback, IModule} from "../interfaces/IERC7579Modules.sol"; -import {CallType} from "../types/Types.sol"; -import { - HOOK_MANAGER_STORAGE_SLOT, - CALLTYPE_DELEGATECALL, - CALLTYPE_SINGLE, - MODULE_TYPE_FALLBACK -} from "../types/Constants.sol"; -import "../types/Error.sol"; +import {IHook} from "../interfaces/IERC7579Modules.sol"; +import {HOOK_MANAGER_STORAGE_SLOT} from "../types/Constants.sol"; +import {ModuleInstallFailed} from "../types/Error.sol"; abstract contract HookManager { struct HookStorage { diff --git a/src/core/ModuleManager.sol b/src/core/ModuleManager.sol index 1150b0c3..8a287dc3 100644 --- a/src/core/ModuleManager.sol +++ b/src/core/ModuleManager.sol @@ -1,18 +1,18 @@ pragma solidity ^0.8.0; -import "../interfaces/IERC7579Modules.sol"; +import {IHook, IExecutor, IModule} from "../interfaces/IERC7579Modules.sol"; import {ValidationManager} from "./ValidationManager.sol"; import {ExecutorManager} from "./ExecutorManager.sol"; import {HookManager} from "./HookManager.sol"; import {SelectorManager} from "./SelectorManager.sol"; import {ERC1271} from "../lib/ERC1271.sol"; -import "../types/Error.sol"; -import "../types/Events.sol"; -import "../types/Structs.sol"; -import "../types/Constants.sol"; -import "../types/Types.sol"; -import "../lib/Utils.sol"; -import "../lib/Lib4337.sol"; +import {InvalidNonce, NotImplemented} from "../types/Error.sol"; +import {ModuleInstalled, ModuleUninstalled} from "../types/Events.sol"; +import {Install, Call, InstallAndExecute} from "../types/Structs.sol"; +import {ValidationId} from "../types/Types.sol"; +import {calldataKeccak} from "../lib/Utils.sol"; +import {Lib4337} from "../lib/Lib4337.sol"; +import {MODULE_MANAGER_STORAGE_SLOT} from "../types/Constants.sol"; struct ModuleStorage { address registry; // Note : not used on vanila kernel but saving the storage slot for future usage diff --git a/src/core/SelectorManager.sol b/src/core/SelectorManager.sol index 6510f4c2..601aa31c 100644 --- a/src/core/SelectorManager.sol +++ b/src/core/SelectorManager.sol @@ -1,15 +1,13 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import {IHook, IFallback, IModule} from "../interfaces/IERC7579Modules.sol"; +import {IHook} from "../interfaces/IERC7579Modules.sol"; import {CallType} from "../types/Types.sol"; import { SELECTOR_MANAGER_STORAGE_SLOT, - CALLTYPE_DELEGATECALL, - CALLTYPE_SINGLE, - MODULE_TYPE_FALLBACK + CALLTYPE_DELEGATECALL } from "../types/Constants.sol"; -import "../types/Error.sol"; +import {ModuleInstallFailed} from "../types/Error.sol"; abstract contract SelectorManager { struct SelectorConfig { diff --git a/src/core/ValidationManager.sol b/src/core/ValidationManager.sol index 30972a70..83ccbcbc 100644 --- a/src/core/ValidationManager.sol +++ b/src/core/ValidationManager.sol @@ -1,11 +1,11 @@ pragma solidity ^0.8.0; import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; -import "../interfaces/IERC7579Modules.sol"; -import "../types/Error.sol"; -import "../types/Types.sol"; -import "../types/Constants.sol"; -import "../types/Structs.sol"; +import {IValidator, IPolicy, ISigner, IHook} from "../interfaces/IERC7579Modules.sol"; +import {InvalidRootValidation, ModuleInstallFailed, OccupiedValidationId, ModuleInstallFailed, InvalidPermissionUninstallOrder, InvalidPermissionUninstallOrder, InvalidPermissionId, InvalidValidator} from "../types/Error.sol"; +import {ValidationId, ValidationType, ValidationMode} from "../types/Types.sol"; +import {VALIDATION_MANAGER_STORAGE_SLOT, VALIDATION_TYPE_ROOT,VALIDATION_TYPE_VALIDATOR,VALIDATION_TYPE_PERMISSION,ERC1271_MAGICVALUE} from "../types/Constants.sol"; +import {ValidationStorage, ValidationInfo, Install} from "../types/Structs.sol"; import {Lib4337} from "../lib/Lib4337.sol"; function parseNonce(uint256 nonce) pure returns (ValidationMode vMode, ValidationType vType, ValidationId vId) { diff --git a/src/interfaces/IERC7579Account.sol b/src/interfaces/IERC7579Account.sol index 4ff76ec4..e1b0d9f8 100644 --- a/src/interfaces/IERC7579Account.sol +++ b/src/interfaces/IERC7579Account.sol @@ -1,8 +1,6 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.21; -import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; - struct Execution { address target; uint256 value; diff --git a/src/lib/ERC1271.sol b/src/lib/ERC1271.sol index 5e040d19..df1f1d72 100644 --- a/src/lib/ERC1271.sol +++ b/src/lib/ERC1271.sol @@ -2,7 +2,6 @@ pragma solidity ^0.8.4; import {EIP712} from "solady/utils/EIP712.sol"; -import {SignatureCheckerLib} from "solady/utils/SignatureCheckerLib.sol"; /// @notice ERC1271 mixin with nested EIP-712 approach. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/accounts/ERC1271.sol) @@ -172,6 +171,7 @@ abstract contract ERC1271 is EIP712 { /// All these are just for widespread out-of-the-box compatibility with other wallet clients. /// We want to create bazaars, not walled castles. /// And we'll use push the Turing Completeness of the EVM to the limits to do so. + /// forge-lint: disable-next-line(mixed-case-function) function _erc1271IsValidSignatureViaNestedEIP712(bytes32 hash, bytes calldata signature) internal view @@ -259,6 +259,7 @@ abstract contract ERC1271 is EIP712 { result = _erc1271IsValidSignatureNowCalldata(hash, signature); } + /// forge-lint: disable-next-line(mixed-case-function) function _erc1271IsValidSignatureViaNestedEIP712Replayable(bytes32 hash, bytes calldata signature) internal view @@ -347,6 +348,7 @@ abstract contract ERC1271 is EIP712 { /// @dev Performs the signature validation without nested EIP-712 to allow for easy sign ins. /// This function must always return false or revert if called on-chain. + /// forge-lint: disable-next-line(mixed-case-function) function _erc1271IsValidSignatureViaRPC(bytes32 hash, bytes calldata signature) internal view diff --git a/src/lib/Lib4337.sol b/src/lib/Lib4337.sol index 2704a4dd..c57e0f09 100644 --- a/src/lib/Lib4337.sol +++ b/src/lib/Lib4337.sol @@ -3,8 +3,6 @@ pragma solidity ^0.8.0; import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; import {UserOperationLib} from "account-abstraction/core/UserOperationLib.sol"; import {Eip7702Support} from "account-abstraction/core/Eip7702Support.sol"; -import {ERC1271_MAGICVALUE, SIG_VALIDATION_FAILED_UINT} from "../types/Constants.sol"; -import {ValidationData} from "../types/Types.sol"; import {IERC5267} from "../interfaces/IERC5267.sol"; library Lib4337 { diff --git a/src/types/Constants.sol b/src/types/Constants.sol index c74ceaa9..dd6d11e3 100644 --- a/src/types/Constants.sol +++ b/src/types/Constants.sol @@ -1,6 +1,6 @@ pragma solidity ^0.8.0; -import "./Types.sol"; +import {CallType, ValidationType, ValidationData} from "./Types.sol"; // Default CallType CallType constant CALLTYPE_SINGLE = CallType.wrap(0x00); diff --git a/src/types/Structs.sol b/src/types/Structs.sol index 0e6de5da..e12febfe 100644 --- a/src/types/Structs.sol +++ b/src/types/Structs.sol @@ -1,6 +1,6 @@ pragma solidity ^0.8.0; -import "./Types.sol"; +import {ValidationId, ValidationType} from "./Types.sol"; struct Install { uint256 moduleType; diff --git a/test/Kernel.t.sol b/test/Kernel.t.sol index 6290254a..bfce9705 100644 --- a/test/Kernel.t.sol +++ b/test/Kernel.t.sol @@ -1,37 +1,21 @@ pragma solidity ^0.8.0; -import {Test} from "forge-std/Test.sol"; import {EntryPointLib} from "./utils/EntryPointLib.sol"; -import {IEntryPoint} from "account-abstraction/interfaces/IEntryPoint.sol"; -import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; -import {Kernel} from "src/Kernel.sol"; import {KernelUUPS} from "src/KernelUUPS.sol"; import {KernelHelper} from "src/KernelHelper.sol"; -import {SelectorManager} from "src/core/SelectorManager.sol"; import {KernelFactory} from "src/KernelFactory.sol"; import {KernelUUPS} from "src/KernelUUPS.sol"; import {KernelImmutableECDSA} from "src/KernelImmutableECDSA.sol"; -import {LibERC7579} from "solady/accounts/LibERC7579.sol"; -import {LibString} from "solady/utils/LibString.sol"; import {Install} from "src/types/Structs.sol"; import {MockFallback} from "./mock/MockFallback.sol"; -import {MockExecutor} from "./mock/MockExecutor.sol"; import {MockValidator} from "./mock/MockValidator.sol"; import {MockHook} from "./mock/MockHook.sol"; import {MockPolicy} from "./mock/MockPolicy.sol"; import {MockSigner} from "./mock/MockSigner.sol"; -import {MockERC721} from "./mock/MockERC721.sol"; -import {MockERC1155} from "./mock/MockERC1155.sol"; -import {MockKernel} from "./mock/MockKernel.sol"; import {MockCallee} from "./mock/MockCallee.sol"; -import {IHook, IValidator} from "src/interfaces/IERC7579Modules.sol"; -import {CallType} from "src/types/Types.sol"; -import "src/types/Constants.sol"; -import "forge-std/console.sol"; -import "src/types/Error.sol"; -import "src/types/Events.sol"; -import "src/types/Structs.sol"; -import {KernelTestBase} from "./KernelTestBase.sol"; +import {NotImplemented} from "src/types/Error.sol"; +import {Install} from "src/types/Structs.sol"; +import {ERC1967_IMPLEMENTATION_SLOT} from "src/types/Constants.sol"; import {KernelUserOpTest} from "./KernelUserOpTest.sol"; import {KernelERC1271Test} from "./KernelERC1271Test.sol"; import {KernelExecutorTest} from "./KernelExecutorTest.sol"; @@ -53,8 +37,8 @@ contract KernelTest is ep = EntryPointLib.deploy(); KernelUUPS uups = new KernelUUPS(ep); - KernelImmutableECDSA immutableECDSA = new KernelImmutableECDSA(ep); - factory = new KernelFactory(uups, immutableECDSA); + KernelImmutableECDSA immutableEcdsa = new KernelImmutableECDSA(ep); + factory = new KernelFactory(uups, immutableEcdsa); helper = new KernelHelper(); newValidator = new MockValidator(); callee = new MockCallee(); diff --git a/test/Kernel7702.t.sol b/test/Kernel7702.t.sol index 9a4b81cd..9f5a305a 100644 --- a/test/Kernel7702.t.sol +++ b/test/Kernel7702.t.sol @@ -1,8 +1,10 @@ pragma solidity ^0.8.0; -import "./Kernel.t.sol"; +import {KernelTest} from "./Kernel.t.sol"; +import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; import {Lib4337} from "src/lib/Lib4337.sol"; import {Kernel7702} from "src/Kernel7702.sol"; +import {Kernel} from "src/Kernel.sol"; contract Kernel7702Test is KernelTest { address owner; diff --git a/test/KernelECDSA.t.sol b/test/KernelECDSA.t.sol index 4e0b4424..04aeb9f3 100644 --- a/test/KernelECDSA.t.sol +++ b/test/KernelECDSA.t.sol @@ -1,8 +1,11 @@ pragma solidity ^0.8.0; -import "./Kernel.t.sol"; +import {KernelTest} from "./Kernel.t.sol"; import {Lib4337} from "src/lib/Lib4337.sol"; import {ECDSAValidator} from "./mock/ECDSAValidator.sol"; +import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; +import {Install, ValidationInfo} from "src/types/Structs.sol"; +import {ValidationId} from "src/types/Types.sol"; contract KernelECDSATest is KernelTest { address owner; @@ -31,9 +34,6 @@ contract KernelECDSATest is KernelTest { assertEq(ValidationId.unwrap(vId), bytes20(address(rootValidator))); ValidationInfo memory info = kernel.validationInfo(vId); - - console.log("vType :"); - console.logBytes1(ValidationType.unwrap(info.vType)); } function _rootSignUserOp(PackedUserOperation memory op, bool success, bool replay) diff --git a/test/KernelERC1271Test.sol b/test/KernelERC1271Test.sol index f9fffb6f..badfd9da 100644 --- a/test/KernelERC1271Test.sol +++ b/test/KernelERC1271Test.sol @@ -1,36 +1,7 @@ pragma solidity ^0.8.0; -import {Test} from "forge-std/Test.sol"; -import {EntryPointLib} from "./utils/EntryPointLib.sol"; -import {IEntryPoint} from "account-abstraction/interfaces/IEntryPoint.sol"; -import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; -import {Kernel} from "src/Kernel.sol"; -import {KernelUUPS} from "src/KernelUUPS.sol"; -import {KernelHelper} from "src/KernelHelper.sol"; -import {SelectorManager} from "src/core/SelectorManager.sol"; -import {KernelFactory} from "src/KernelFactory.sol"; -import {KernelUUPS} from "src/KernelUUPS.sol"; -import {KernelImmutableECDSA} from "src/KernelImmutableECDSA.sol"; -import {LibERC7579} from "solady/accounts/LibERC7579.sol"; import {LibString} from "solady/utils/LibString.sol"; -import {Install} from "src/types/Structs.sol"; -import {MockFallback} from "./mock/MockFallback.sol"; -import {MockExecutor} from "./mock/MockExecutor.sol"; -import {MockValidator} from "./mock/MockValidator.sol"; -import {MockHook} from "./mock/MockHook.sol"; -import {MockPolicy} from "./mock/MockPolicy.sol"; -import {MockSigner} from "./mock/MockSigner.sol"; -import {MockERC721} from "./mock/MockERC721.sol"; -import {MockERC1155} from "./mock/MockERC1155.sol"; -import {MockCallee} from "./mock/MockCallee.sol"; -import {MockKernel} from "./mock/MockKernel.sol"; -import {IHook, IValidator} from "src/interfaces/IERC7579Modules.sol"; -import {CallType} from "src/types/Types.sol"; -import "src/types/Constants.sol"; -import "forge-std/console.sol"; -import "src/types/Error.sol"; -import "src/types/Events.sol"; -import "src/types/Structs.sol"; +import {ERC1271_MAGICVALUE, ERC1271_INVALID} from "src/types/Constants.sol"; import {KernelTestBase} from "./KernelTestBase.sol"; abstract contract KernelERC1271Test is KernelTestBase { @@ -68,7 +39,7 @@ abstract contract KernelERC1271Test is KernelTestBase { function test_erc1271_root_personal_sign() external unitTest { bytes32 messageHash = keccak256("Hello world"); - bytes32 personalHash = _toERC1271HashPersonalSign(messageHash); + bytes32 personalHash = _toErc1271HashPersonalSign(messageHash); bytes memory sig = _rootSignHash(personalHash, true); bytes4 ret = kernel.isValidSignature(messageHash, abi.encodePacked(bytes20(0), sig)); assertEq(ret, ERC1271_MAGICVALUE); @@ -76,7 +47,7 @@ abstract contract KernelERC1271Test is KernelTestBase { function test_erc1271_root_personal_sign_fail() external unitTest { bytes32 messageHash = keccak256("Hello world"); - bytes32 personalHash = _toERC1271HashPersonalSign(messageHash); + bytes32 personalHash = _toErc1271HashPersonalSign(messageHash); bytes memory sig = _rootSignHash(personalHash, false); bytes4 ret = kernel.isValidSignature(messageHash, abi.encodePacked(bytes20(0), sig)); assertEq(ret, ERC1271_INVALID); @@ -106,7 +77,7 @@ abstract contract KernelERC1271Test is KernelTestBase { function test_erc1271_validator_personal_sign() external unitTest { bytes32 messageHash = keccak256("Hello world"); - bytes32 personalHash = _toERC1271HashPersonalSign(messageHash); + bytes32 personalHash = _toErc1271HashPersonalSign(messageHash); bytes memory sig = _validatorSignHash(personalHash, true); kernel.installModule(1, address(newValidator), abi.encode(hex"", hex"")); bytes4 ret = kernel.isValidSignature(messageHash, abi.encodePacked(bytes20(address(newValidator)), sig)); @@ -115,7 +86,7 @@ abstract contract KernelERC1271Test is KernelTestBase { function test_erc1271_validator_personal_sign_fail() external unitTest { bytes32 messageHash = keccak256("Hello world"); - bytes32 personalHash = _toERC1271HashPersonalSign(messageHash); + bytes32 personalHash = _toErc1271HashPersonalSign(messageHash); bytes memory sig = _validatorSignHash(personalHash, false); kernel.installModule(1, address(newValidator), abi.encode(hex"", hex"")); bytes4 ret = kernel.isValidSignature(messageHash, abi.encodePacked(bytes20(address(newValidator)), sig)); @@ -144,7 +115,7 @@ abstract contract KernelERC1271Test is KernelTestBase { function test_erc1271_permission_personal_sign() external unitTest { bytes32 messageHash = keccak256("Hello world"); - bytes32 personalHash = _toERC1271HashPersonalSign(messageHash); + bytes32 personalHash = _toErc1271HashPersonalSign(messageHash); bytes memory sig = _permissionSignHash(personalHash, true); kernel.installModule(5, address(policy), abi.encode(hex"deadbeef", abi.encodePacked(permissionId))); kernel.installModule(6, address(signer), abi.encode(hex"deadbeef", abi.encodePacked(permissionId))); @@ -154,7 +125,7 @@ abstract contract KernelERC1271Test is KernelTestBase { function test_erc1271_permission_personal_sign_fail() external unitTest { bytes32 messageHash = keccak256("Hello world"); - bytes32 personalHash = _toERC1271HashPersonalSign(messageHash); + bytes32 personalHash = _toErc1271HashPersonalSign(messageHash); bytes memory sig = _permissionSignHash(personalHash, false); kernel.installModule(5, address(policy), abi.encode(hex"deadbeef", abi.encodePacked(permissionId))); kernel.installModule(6, address(signer), abi.encode(hex"deadbeef", abi.encodePacked(permissionId))); @@ -176,9 +147,9 @@ abstract contract KernelERC1271Test is KernelTestBase { contentsHash = keccak256(abi.encode(hash, contentsType)); bytes32 actualHash; if (isExplicit) { - actualHash = _toERC1271Hash(address(kernel), contentsHash, contentsType, contentsName); + actualHash = _toErc1271Hash(address(kernel), contentsHash, contentsType, contentsName); } else { - actualHash = _toERC1271Hash(address(kernel), contentsHash, contentsType, _contentsName(contentsType)); + actualHash = _toErc1271Hash(address(kernel), contentsHash, contentsType, _contentsName(contentsType)); } sig = signFn(actualHash, success); bytes memory contentsDescription = abi.encodePacked(contentsType, contentsName); @@ -187,7 +158,7 @@ abstract contract KernelERC1271Test is KernelTestBase { abi.encodePacked(sig, _DOMAIN_SEP_B, contentsHash, contentsDescription, uint16(contentsDescription.length)); } - function _toERC1271Hash(address account, bytes32 contents, bytes memory contentsType, bytes memory contentsName) + function _toErc1271Hash(address account, bytes32 contents, bytes memory contentsType, bytes memory contentsName) internal view returns (bytes32) @@ -201,7 +172,7 @@ abstract contract KernelERC1271Test is KernelTestBase { return keccak256(abi.encodePacked("\x19\x01", _DOMAIN_SEP_B, parentStructHash)); } - struct _AccountDomainStruct { + struct AccountDomainStruct { string name; string version; uint256 chainId; @@ -214,14 +185,14 @@ abstract contract KernelERC1271Test is KernelTestBase { } function _accountDomainStructFields(address account) internal view returns (bytes memory) { - _AccountDomainStruct memory t; + AccountDomainStruct memory t; (, t.name, t.version, t.chainId, t.verifyingContract, t.salt,) = kernel.eip712Domain(); return abi.encode(keccak256(bytes(t.name)), keccak256(bytes(t.version)), t.chainId, t.verifyingContract, t.salt); } - function _toERC1271HashPersonalSign(bytes32 childHash) internal view returns (bytes32) { - _AccountDomainStruct memory t; + function _toErc1271HashPersonalSign(bytes32 childHash) internal view returns (bytes32) { + AccountDomainStruct memory t; (, t.name, t.version, t.chainId, t.verifyingContract, t.salt,) = kernel.eip712Domain(); bytes32 domainSeparator = keccak256( diff --git a/test/KernelExecuteTest.sol b/test/KernelExecuteTest.sol index da6d848d..7a52dad6 100644 --- a/test/KernelExecuteTest.sol +++ b/test/KernelExecuteTest.sol @@ -1,37 +1,10 @@ pragma solidity ^0.8.0; -import {Test} from "forge-std/Test.sol"; -import {EntryPointLib} from "./utils/EntryPointLib.sol"; -import {IEntryPoint} from "account-abstraction/interfaces/IEntryPoint.sol"; -import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; -import {Kernel} from "src/Kernel.sol"; -import {KernelUUPS} from "src/KernelUUPS.sol"; -import {KernelHelper} from "src/KernelHelper.sol"; -import {SelectorManager} from "src/core/SelectorManager.sol"; -import {KernelFactory} from "src/KernelFactory.sol"; -import {KernelUUPS} from "src/KernelUUPS.sol"; -import {KernelImmutableECDSA} from "src/KernelImmutableECDSA.sol"; import {LibERC7579} from "solady/accounts/LibERC7579.sol"; -import {LibString} from "solady/utils/LibString.sol"; -import {Install} from "src/types/Structs.sol"; -import {MockFallback} from "./mock/MockFallback.sol"; -import {MockExecutor} from "./mock/MockExecutor.sol"; -import {MockValidator} from "./mock/MockValidator.sol"; -import {MockHook} from "./mock/MockHook.sol"; -import {MockPolicy} from "./mock/MockPolicy.sol"; -import {MockSigner} from "./mock/MockSigner.sol"; -import {MockERC721} from "./mock/MockERC721.sol"; -import {MockERC1155} from "./mock/MockERC1155.sol"; import {MockCallee} from "./mock/MockCallee.sol"; -import {MockKernel} from "./mock/MockKernel.sol"; -import {IHook, IValidator} from "src/interfaces/IERC7579Modules.sol"; -import {CallType} from "src/types/Types.sol"; -import "src/types/Constants.sol"; -import "forge-std/console.sol"; -import "src/types/Error.sol"; -import "src/types/Events.sol"; -import "src/types/Structs.sol"; import {KernelTestBase} from "./KernelTestBase.sol"; +import {InvalidCallType, InvalidExecType} from "src/types/Error.sol"; +import {Call} from "src/types/Structs.sol"; abstract contract KernelExecuteTest is KernelTestBase { function test_execute() external unitTest { diff --git a/test/KernelExecutorTest.sol b/test/KernelExecutorTest.sol index 1c6a8975..1a47ed95 100644 --- a/test/KernelExecutorTest.sol +++ b/test/KernelExecutorTest.sol @@ -1,36 +1,11 @@ pragma solidity ^0.8.0; -import {Test} from "forge-std/Test.sol"; -import {EntryPointLib} from "./utils/EntryPointLib.sol"; -import {IEntryPoint} from "account-abstraction/interfaces/IEntryPoint.sol"; -import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; -import {Kernel} from "src/Kernel.sol"; -import {KernelUUPS} from "src/KernelUUPS.sol"; -import {KernelHelper} from "src/KernelHelper.sol"; -import {SelectorManager} from "src/core/SelectorManager.sol"; -import {KernelFactory} from "src/KernelFactory.sol"; -import {KernelUUPS} from "src/KernelUUPS.sol"; -import {KernelImmutableECDSA} from "src/KernelImmutableECDSA.sol"; import {LibERC7579} from "solady/accounts/LibERC7579.sol"; -import {LibString} from "solady/utils/LibString.sol"; -import {Install} from "src/types/Structs.sol"; -import {MockFallback} from "./mock/MockFallback.sol"; +import {Install, Call, InstallAndExecute} from "src/types/Structs.sol"; +import {ERC1967_IMPLEMENTATION_SLOT} from "src/types/Constants.sol"; import {MockExecutor} from "./mock/MockExecutor.sol"; -import {MockValidator} from "./mock/MockValidator.sol"; -import {MockHook} from "./mock/MockHook.sol"; -import {MockPolicy} from "./mock/MockPolicy.sol"; -import {MockSigner} from "./mock/MockSigner.sol"; -import {MockERC721} from "./mock/MockERC721.sol"; -import {MockERC1155} from "./mock/MockERC1155.sol"; import {MockCallee} from "./mock/MockCallee.sol"; import {MockKernel} from "./mock/MockKernel.sol"; -import {IHook, IValidator} from "src/interfaces/IERC7579Modules.sol"; -import {CallType} from "src/types/Types.sol"; -import "src/types/Constants.sol"; -import "forge-std/console.sol"; -import "src/types/Error.sol"; -import "src/types/Events.sol"; -import "src/types/Structs.sol"; import {KernelTestBase} from "./KernelTestBase.sol"; abstract contract KernelExecutorTest is KernelTestBase { diff --git a/test/KernelFactory.t.sol b/test/KernelFactory.t.sol index feb5345e..aec0881f 100644 --- a/test/KernelFactory.t.sol +++ b/test/KernelFactory.t.sol @@ -1,37 +1,21 @@ pragma solidity ^0.8.0; -import {Test} from "forge-std/Test.sol"; import {EntryPointLib} from "./utils/EntryPointLib.sol"; -import {IEntryPoint} from "account-abstraction/interfaces/IEntryPoint.sol"; -import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; import {Kernel} from "src/Kernel.sol"; import {KernelUUPS} from "src/KernelUUPS.sol"; import {KernelHelper} from "src/KernelHelper.sol"; -import {SelectorManager} from "src/core/SelectorManager.sol"; import {KernelFactory} from "src/KernelFactory.sol"; import {KernelUUPS} from "src/KernelUUPS.sol"; import {KernelImmutableECDSA} from "src/KernelImmutableECDSA.sol"; -import {LibERC7579} from "solady/accounts/LibERC7579.sol"; -import {LibString} from "solady/utils/LibString.sol"; -import {Install} from "src/types/Structs.sol"; +import {Install, ValidationInfo} from "src/types/Structs.sol"; +import {VALIDATION_TYPE_VALIDATOR} from "src/types/Constants.sol"; +import {ValidationId} from "src/types/Types.sol"; import {MockFallback} from "./mock/MockFallback.sol"; -import {MockExecutor} from "./mock/MockExecutor.sol"; import {MockValidator} from "./mock/MockValidator.sol"; -import {MockHook} from "./mock/MockHook.sol"; import {MockPolicy} from "./mock/MockPolicy.sol"; import {MockSigner} from "./mock/MockSigner.sol"; -import {MockERC721} from "./mock/MockERC721.sol"; -import {MockERC1155} from "./mock/MockERC1155.sol"; -import {MockKernel} from "./mock/MockKernel.sol"; import {MockCallee} from "./mock/MockCallee.sol"; -import {MockContractETH} from "./mock/MockContractETH.sol"; -import {IHook, IValidator} from "src/interfaces/IERC7579Modules.sol"; -import {CallType} from "src/types/Types.sol"; -import "src/types/Constants.sol"; -import "forge-std/console.sol"; -import "src/types/Error.sol"; -import "src/types/Events.sol"; -import "src/types/Structs.sol"; +import {InvalidRootValidation} from "src/types/Error.sol"; import {KernelTestBase} from "./KernelTestBase.sol"; contract KernelFactoryTest is KernelTestBase { @@ -39,8 +23,8 @@ contract KernelFactoryTest is KernelTestBase { ep = EntryPointLib.deploy(); KernelUUPS uups = new KernelUUPS(ep); - KernelImmutableECDSA immutableECDSA = new KernelImmutableECDSA(ep); - factory = new KernelFactory(uups, immutableECDSA); + KernelImmutableECDSA immutableEcdsa = new KernelImmutableECDSA(ep); + factory = new KernelFactory(uups, immutableEcdsa); helper = new KernelHelper(); newValidator = new MockValidator(); callee = new MockCallee(); diff --git a/test/KernelHookTest.sol b/test/KernelHookTest.sol index 2452021e..26d4580f 100644 --- a/test/KernelHookTest.sol +++ b/test/KernelHookTest.sol @@ -1,36 +1,6 @@ pragma solidity ^0.8.0; -import {Test} from "forge-std/Test.sol"; -import {EntryPointLib} from "./utils/EntryPointLib.sol"; -import {IEntryPoint} from "account-abstraction/interfaces/IEntryPoint.sol"; -import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; -import {Kernel} from "src/Kernel.sol"; -import {KernelUUPS} from "src/KernelUUPS.sol"; -import {KernelHelper} from "src/KernelHelper.sol"; -import {SelectorManager} from "src/core/SelectorManager.sol"; -import {KernelFactory} from "src/KernelFactory.sol"; -import {KernelUUPS} from "src/KernelUUPS.sol"; -import {KernelImmutableECDSA} from "src/KernelImmutableECDSA.sol"; -import {LibERC7579} from "solady/accounts/LibERC7579.sol"; -import {LibString} from "solady/utils/LibString.sol"; -import {Install} from "src/types/Structs.sol"; -import {MockFallback} from "./mock/MockFallback.sol"; -import {MockExecutor} from "./mock/MockExecutor.sol"; -import {MockValidator} from "./mock/MockValidator.sol"; import {MockHook} from "./mock/MockHook.sol"; -import {MockPolicy} from "./mock/MockPolicy.sol"; -import {MockSigner} from "./mock/MockSigner.sol"; -import {MockERC721} from "./mock/MockERC721.sol"; -import {MockERC1155} from "./mock/MockERC1155.sol"; -import {MockCallee} from "./mock/MockCallee.sol"; -import {MockKernel} from "./mock/MockKernel.sol"; -import {IHook, IValidator} from "src/interfaces/IERC7579Modules.sol"; -import {CallType} from "src/types/Types.sol"; -import "src/types/Constants.sol"; -import "forge-std/console.sol"; -import "src/types/Error.sol"; -import "src/types/Events.sol"; -import "src/types/Structs.sol"; import {KernelTestBase} from "./KernelTestBase.sol"; abstract contract KernelHookTest is KernelTestBase { diff --git a/test/KernelImmutableECDSA.t.sol b/test/KernelImmutableECDSA.t.sol index 98a12ef0..246cb0c6 100644 --- a/test/KernelImmutableECDSA.t.sol +++ b/test/KernelImmutableECDSA.t.sol @@ -1,6 +1,8 @@ pragma solidity ^0.8.0; -import "./Kernel.t.sol"; +import {KernelTest} from "./Kernel.t.sol"; +import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; +import {Install} from "src/types/Structs.sol"; import {Lib4337} from "src/lib/Lib4337.sol"; import {ECDSAValidator} from "./mock/ECDSAValidator.sol"; @@ -31,9 +33,6 @@ contract KernelImmutableECDSATest is KernelTest { } function _rootSignHash(bytes32 hash, bool success) internal override returns (bytes memory sig) { - console.log("Owner :", owner); - console.log("Code :"); - console.logBytes(address(kernel).code); if (!success) { hash = keccak256(abi.encodePacked(hash)); } diff --git a/test/KernelSelectorTest.sol b/test/KernelSelectorTest.sol index 9b0e7a0a..f0cbf4c3 100644 --- a/test/KernelSelectorTest.sol +++ b/test/KernelSelectorTest.sol @@ -1,37 +1,11 @@ pragma solidity ^0.8.0; -import {Test} from "forge-std/Test.sol"; -import {EntryPointLib} from "./utils/EntryPointLib.sol"; -import {IEntryPoint} from "account-abstraction/interfaces/IEntryPoint.sol"; -import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; -import {Kernel} from "src/Kernel.sol"; -import {KernelUUPS} from "src/KernelUUPS.sol"; -import {KernelHelper} from "src/KernelHelper.sol"; import {SelectorManager} from "src/core/SelectorManager.sol"; -import {KernelFactory} from "src/KernelFactory.sol"; -import {KernelUUPS} from "src/KernelUUPS.sol"; -import {KernelImmutableECDSA} from "src/KernelImmutableECDSA.sol"; -import {LibERC7579} from "solady/accounts/LibERC7579.sol"; -import {LibString} from "solady/utils/LibString.sol"; -import {Install} from "src/types/Structs.sol"; import {MockFallback} from "./mock/MockFallback.sol"; -import {MockExecutor} from "./mock/MockExecutor.sol"; -import {MockValidator} from "./mock/MockValidator.sol"; import {MockHook} from "./mock/MockHook.sol"; -import {MockPolicy} from "./mock/MockPolicy.sol"; -import {MockSigner} from "./mock/MockSigner.sol"; -import {MockERC721} from "./mock/MockERC721.sol"; -import {MockERC1155} from "./mock/MockERC1155.sol"; -import {MockCallee} from "./mock/MockCallee.sol"; -import {MockKernel} from "./mock/MockKernel.sol"; -import {IHook, IValidator} from "src/interfaces/IERC7579Modules.sol"; import {CallType} from "src/types/Types.sol"; -import "src/types/Constants.sol"; -import "forge-std/console.sol"; -import "src/types/Error.sol"; -import "src/types/Events.sol"; -import "src/types/Structs.sol"; import {KernelTestBase} from "./KernelTestBase.sol"; +import {InvalidSelector} from "src/types/Error.sol"; abstract contract KernelSelectorTest is KernelTestBase { function test_install_selector_call() external unitTest { diff --git a/test/KernelTestBase.sol b/test/KernelTestBase.sol index 85f86cd3..001aadea 100644 --- a/test/KernelTestBase.sol +++ b/test/KernelTestBase.sol @@ -1,23 +1,14 @@ pragma solidity ^0.8.0; import {Test} from "forge-std/Test.sol"; -import {EntryPointLib} from "./utils/EntryPointLib.sol"; import {IEntryPoint} from "account-abstraction/interfaces/IEntryPoint.sol"; import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; import {Kernel} from "src/Kernel.sol"; -import {KernelUUPS} from "src/KernelUUPS.sol"; import {KernelHelper} from "src/KernelHelper.sol"; -import {SelectorManager} from "src/core/SelectorManager.sol"; import {KernelFactory} from "src/KernelFactory.sol"; -import {KernelUUPS} from "src/KernelUUPS.sol"; -import {KernelImmutableECDSA} from "src/KernelImmutableECDSA.sol"; -import {LibERC7579} from "solady/accounts/LibERC7579.sol"; -import {LibString} from "solady/utils/LibString.sol"; import {Install} from "src/types/Structs.sol"; import {MockFallback} from "./mock/MockFallback.sol"; -import {MockExecutor} from "./mock/MockExecutor.sol"; import {MockValidator} from "./mock/MockValidator.sol"; -import {MockHook} from "./mock/MockHook.sol"; import {MockPolicy} from "./mock/MockPolicy.sol"; import {MockSigner} from "./mock/MockSigner.sol"; import {MockERC721} from "./mock/MockERC721.sol"; @@ -25,13 +16,11 @@ import {MockERC1155} from "./mock/MockERC1155.sol"; import {MockCallee} from "./mock/MockCallee.sol"; import {MockContractETH} from "./mock/MockContractETH.sol"; import {MockKernel} from "./mock/MockKernel.sol"; -import {IHook, IValidator} from "src/interfaces/IERC7579Modules.sol"; -import {CallType} from "src/types/Types.sol"; -import "src/types/Constants.sol"; -import "forge-std/console.sol"; -import "src/types/Error.sol"; -import "src/types/Events.sol"; -import "src/types/Structs.sol"; +import {IValidator} from "src/interfaces/IERC7579Modules.sol"; +import {console} from "forge-std/console.sol"; +import {Received} from "src/types/Events.sol"; +import {Install} from "src/types/Structs.sol"; +import {ValidationMode} from "src/types/Types.sol"; abstract contract KernelTestBase is Test { IEntryPoint ep; @@ -220,7 +209,7 @@ abstract contract KernelTestBase is Test { function test_codesize() external { vm.skip(true); - address implementation = address(factory.uups()); + address implementation = address(factory.UUPS()); console.log("Code size :", implementation.code.length); require(implementation.code.length <= 24576, "Code too big"); console.log("space left :", 24576 - implementation.code.length); diff --git a/test/KernelUserOpTest.sol b/test/KernelUserOpTest.sol index 24bde7f3..2668fccd 100644 --- a/test/KernelUserOpTest.sol +++ b/test/KernelUserOpTest.sol @@ -1,36 +1,9 @@ pragma solidity ^0.8.0; -import {Test} from "forge-std/Test.sol"; -import {EntryPointLib} from "./utils/EntryPointLib.sol"; import {IEntryPoint} from "account-abstraction/interfaces/IEntryPoint.sol"; import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; import {Kernel} from "src/Kernel.sol"; -import {KernelUUPS} from "src/KernelUUPS.sol"; -import {KernelHelper} from "src/KernelHelper.sol"; -import {SelectorManager} from "src/core/SelectorManager.sol"; -import {KernelFactory} from "src/KernelFactory.sol"; -import {KernelUUPS} from "src/KernelUUPS.sol"; -import {KernelImmutableECDSA} from "src/KernelImmutableECDSA.sol"; -import {LibERC7579} from "solady/accounts/LibERC7579.sol"; -import {LibString} from "solady/utils/LibString.sol"; -import {Install} from "src/types/Structs.sol"; -import {MockFallback} from "./mock/MockFallback.sol"; -import {MockExecutor} from "./mock/MockExecutor.sol"; -import {MockValidator} from "./mock/MockValidator.sol"; -import {MockHook} from "./mock/MockHook.sol"; -import {MockPolicy} from "./mock/MockPolicy.sol"; -import {MockSigner} from "./mock/MockSigner.sol"; -import {MockERC721} from "./mock/MockERC721.sol"; -import {MockERC1155} from "./mock/MockERC1155.sol"; import {MockCallee} from "./mock/MockCallee.sol"; -import {MockKernel} from "./mock/MockKernel.sol"; -import {IHook, IValidator} from "src/interfaces/IERC7579Modules.sol"; -import {CallType} from "src/types/Types.sol"; -import "src/types/Constants.sol"; -import "forge-std/console.sol"; -import "src/types/Error.sol"; -import "src/types/Events.sol"; -import "src/types/Structs.sol"; import {KernelTestBase} from "./KernelTestBase.sol"; abstract contract KernelUserOpTest is KernelTestBase { diff --git a/test/KernelValidatorTest.sol b/test/KernelValidatorTest.sol index 115d17e2..965dcd26 100644 --- a/test/KernelValidatorTest.sol +++ b/test/KernelValidatorTest.sol @@ -1,37 +1,17 @@ pragma solidity ^0.8.0; -import {Test} from "forge-std/Test.sol"; -import {EntryPointLib} from "./utils/EntryPointLib.sol"; -import {IEntryPoint} from "account-abstraction/interfaces/IEntryPoint.sol"; -import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; -import {Kernel} from "src/Kernel.sol"; -import {KernelUUPS} from "src/KernelUUPS.sol"; -import {KernelHelper} from "src/KernelHelper.sol"; -import {SelectorManager} from "src/core/SelectorManager.sol"; -import {KernelFactory} from "src/KernelFactory.sol"; -import {KernelUUPS} from "src/KernelUUPS.sol"; -import {KernelImmutableECDSA} from "src/KernelImmutableECDSA.sol"; -import {LibERC7579} from "solady/accounts/LibERC7579.sol"; -import {LibString} from "solady/utils/LibString.sol"; -import {Install} from "src/types/Structs.sol"; -import {MockFallback} from "./mock/MockFallback.sol"; -import {MockExecutor} from "./mock/MockExecutor.sol"; -import {MockValidator} from "./mock/MockValidator.sol"; -import {MockHook} from "./mock/MockHook.sol"; +import {Install, ValidationInfo} from "src/types/Structs.sol"; +import {ValidationId} from "src/types/Types.sol"; import {MockPolicy} from "./mock/MockPolicy.sol"; import {MockSigner} from "./mock/MockSigner.sol"; -import {MockERC721} from "./mock/MockERC721.sol"; -import {MockERC1155} from "./mock/MockERC1155.sol"; -import {MockCallee} from "./mock/MockCallee.sol"; -import {MockKernel} from "./mock/MockKernel.sol"; -import {IHook, IValidator} from "src/interfaces/IERC7579Modules.sol"; -import {CallType} from "src/types/Types.sol"; -import "src/types/Constants.sol"; -import "forge-std/console.sol"; -import "src/types/Error.sol"; -import "src/types/Events.sol"; -import "src/types/Structs.sol"; import {KernelTestBase} from "./KernelTestBase.sol"; +import {InvalidNonce} from "src/types/Error.sol"; +import { + VALIDATION_TYPE_ROOT, + VALIDATION_TYPE_VALIDATOR, + VALIDATION_TYPE_PERMISSION, + ERC1271_MAGICVALUE +} from "src/types/Constants.sol"; abstract contract KernelValidatorTest is KernelTestBase { function test_set_valid_nonce() external unitTest { diff --git a/test/mock/ECDSAValidator.sol b/test/mock/ECDSAValidator.sol index 54b2106f..cf8cc1d1 100644 --- a/test/mock/ECDSAValidator.sol +++ b/test/mock/ECDSAValidator.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.0; import {ECDSA} from "solady/utils/ECDSA.sol"; -import {IValidator, IHook} from "src/interfaces/IERC7579Modules.sol"; +import {IValidator} from "src/interfaces/IERC7579Modules.sol"; import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; import { SIG_VALIDATION_SUCCESS_UINT, @@ -14,6 +14,7 @@ import { ERC1271_INVALID } from "src/types/Constants.sol"; +/// forge-lint: disable-next-item(pascal-case-struct) struct ECDSAValidatorStorage { address owner; } @@ -34,8 +35,8 @@ contract ECDSAValidator is IValidator { delete ecdsaValidatorStorage[msg.sender]; } - function isModuleType(uint256 typeID) external pure override returns (bool) { - return typeID == MODULE_TYPE_VALIDATOR || typeID == MODULE_TYPE_HOOK; + function isModuleType(uint256 typeId) external pure override returns (bool) { + return typeId == MODULE_TYPE_VALIDATOR || typeId == MODULE_TYPE_HOOK; } function isInitialized(address smartAccount) external view override returns (bool) { diff --git a/test/mock/MockERC1155.sol b/test/mock/MockERC1155.sol index cf758e2a..5db937aa 100644 --- a/test/mock/MockERC1155.sol +++ b/test/mock/MockERC1155.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import "solady/tokens/ERC1155.sol"; +import {ERC1155} from "solady/tokens/ERC1155.sol"; contract MockERC1155 is ERC1155 { function test_ignore() public {} diff --git a/test/mock/MockERC20.sol b/test/mock/MockERC20.sol index 18410054..df1f6098 100644 --- a/test/mock/MockERC20.sol +++ b/test/mock/MockERC20.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import "solady/tokens/ERC20.sol"; +import {ERC20} from "solady/tokens/ERC20.sol"; contract MockERC20 is ERC20 { - constructor() ERC20() {} + constructor() {} function test_ignore() public {} diff --git a/test/mock/MockERC721.sol b/test/mock/MockERC721.sol index 4cc30766..39b37abe 100644 --- a/test/mock/MockERC721.sol +++ b/test/mock/MockERC721.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import "solady/tokens/ERC721.sol"; +import {ERC721} from "solady/tokens/ERC721.sol"; contract MockERC721 is ERC721 { - constructor() ERC721() {} + constructor() {} function test_ignore() public {} @@ -15,7 +15,7 @@ contract MockERC721 is ERC721 { function symbol() public pure override returns (string memory) { return "MOCK"; } - + /// forge-lint: disable-next-line(mixed-case-function) function tokenURI(uint256) public pure override returns (string memory) { return ""; } diff --git a/test/mock/MockFallback.sol b/test/mock/MockFallback.sol index d566fd02..90dac8aa 100644 --- a/test/mock/MockFallback.sol +++ b/test/mock/MockFallback.sol @@ -3,7 +3,6 @@ pragma solidity ^0.8.0; import {IERC7579Account} from "src/interfaces/IERC7579Account.sol"; import {IFallback} from "src/interfaces/IERC7579Modules.sol"; -import {CallType, ExecType, ExecMode} from "src/types/Types.sol"; contract Callee { address public lastCaller; diff --git a/test/mock/MockKernel.sol b/test/mock/MockKernel.sol index 440888a9..27f4a1f6 100644 --- a/test/mock/MockKernel.sol +++ b/test/mock/MockKernel.sol @@ -1,7 +1,7 @@ pragma solidity ^0.8.0; -import "src/Kernel.sol"; -import "forge-std/console.sol"; +import {IEntryPoint, Kernel} from "src/Kernel.sol"; +import {Call, Install, InstallAndExecute} from "src/types/Structs.sol"; // NOTE: this is not for real usecase, just a contract to deploy for test checks contract MockKernel is Kernel { diff --git a/test/mock/MockPolicy.sol b/test/mock/MockPolicy.sol index a67d1897..d0329817 100644 --- a/test/mock/MockPolicy.sol +++ b/test/mock/MockPolicy.sol @@ -4,7 +4,6 @@ pragma solidity ^0.8.0; import {IPolicy} from "src/interfaces/IERC7579Modules.sol"; import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; -import "forge-std/console.sol"; contract MockPolicy is IPolicy { mapping(address => mapping(bytes32 => bool)) public pass; diff --git a/test/mock/MockSigner.sol b/test/mock/MockSigner.sol index 5d76f18b..760cefc6 100644 --- a/test/mock/MockSigner.sol +++ b/test/mock/MockSigner.sol @@ -2,7 +2,8 @@ pragma solidity ^0.8.0; -import "src/interfaces/IERC7579Modules.sol"; +import {ISigner} from "src/interfaces/IERC7579Modules.sol"; +import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; contract MockSigner is ISigner { mapping(address wallet => bytes) public data; diff --git a/test/mock/MockValidator.sol b/test/mock/MockValidator.sol index 997fb4ff..91da213a 100644 --- a/test/mock/MockValidator.sol +++ b/test/mock/MockValidator.sol @@ -2,7 +2,8 @@ pragma solidity ^0.8.0; -import "src/interfaces/IERC7579Modules.sol"; +import {IValidator, IHook} from "src/interfaces/IERC7579Modules.sol"; +import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; contract MockValidator is IValidator, IHook { mapping(address => bool) public initialized; @@ -36,8 +37,8 @@ contract MockValidator is IValidator, IHook { validatorData[msg.sender] = data; } - function isModuleType(uint256 typeID) external pure returns (bool) { - return typeID == 1; + function isModuleType(uint256 typeId) external pure returns (bool) { + return typeId == 1; } /** From 47d31197595c87c8cf770be628f24ae2a633d235 Mon Sep 17 00:00:00 2001 From: leekt Date: Thu, 25 Sep 2025 14:36:05 +0900 Subject: [PATCH 057/121] fmt --- src/Kernel.sol | 21 ++++++++++++++++++--- src/core/SelectorManager.sol | 5 +---- src/core/ValidationManager.sol | 19 +++++++++++++++++-- test/mock/MockERC721.sol | 1 + 4 files changed, 37 insertions(+), 9 deletions(-) diff --git a/src/Kernel.sol b/src/Kernel.sol index b66beb59..31106d25 100644 --- a/src/Kernel.sol +++ b/src/Kernel.sol @@ -8,11 +8,26 @@ import {parseNonce} from "./core/ValidationManager.sol"; import {ExecutionManager} from "./core/ExecutionManager.sol"; import {Lib4337} from "./lib/Lib4337.sol"; import {LibERC7579} from "solady/accounts/LibERC7579.sol"; -import {CallType, ValidationId, ValidationMode, ValidationType, isEnable, isReplayable, isEnableReplayable} from "./types/Types.sol"; -import {NotImplemented,Unauthorized,UnauthorizedCallData, InvalidSelector, InvalidInitialization, InstallSignatureVerificationFailed} from "./types/Error.sol"; +import { + CallType, + ValidationId, + ValidationMode, + ValidationType, + isEnable, + isReplayable, + isEnableReplayable +} from "./types/Types.sol"; +import { + NotImplemented, + Unauthorized, + UnauthorizedCallData, + InvalidSelector, + InvalidInitialization, + InstallSignatureVerificationFailed +} from "./types/Error.sol"; import {Received} from "./types/Events.sol"; import {VALIDATION_TYPE_ROOT} from "./types/Constants.sol"; -import {ValidationStorage, ValidationInfo} from "./types/Structs.sol"; +import {ValidationStorage, ValidationInfo} from "./types/Structs.sol"; abstract contract Kernel is ModuleManager, ExecutionManager { IEntryPoint immutable ENTRYPOINT; diff --git a/src/core/SelectorManager.sol b/src/core/SelectorManager.sol index 601aa31c..28ac844f 100644 --- a/src/core/SelectorManager.sol +++ b/src/core/SelectorManager.sol @@ -3,10 +3,7 @@ pragma solidity ^0.8.0; import {IHook} from "../interfaces/IERC7579Modules.sol"; import {CallType} from "../types/Types.sol"; -import { - SELECTOR_MANAGER_STORAGE_SLOT, - CALLTYPE_DELEGATECALL -} from "../types/Constants.sol"; +import {SELECTOR_MANAGER_STORAGE_SLOT, CALLTYPE_DELEGATECALL} from "../types/Constants.sol"; import {ModuleInstallFailed} from "../types/Error.sol"; abstract contract SelectorManager { diff --git a/src/core/ValidationManager.sol b/src/core/ValidationManager.sol index 83ccbcbc..70a528fe 100644 --- a/src/core/ValidationManager.sol +++ b/src/core/ValidationManager.sol @@ -2,9 +2,24 @@ pragma solidity ^0.8.0; import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; import {IValidator, IPolicy, ISigner, IHook} from "../interfaces/IERC7579Modules.sol"; -import {InvalidRootValidation, ModuleInstallFailed, OccupiedValidationId, ModuleInstallFailed, InvalidPermissionUninstallOrder, InvalidPermissionUninstallOrder, InvalidPermissionId, InvalidValidator} from "../types/Error.sol"; +import { + InvalidRootValidation, + ModuleInstallFailed, + OccupiedValidationId, + ModuleInstallFailed, + InvalidPermissionUninstallOrder, + InvalidPermissionUninstallOrder, + InvalidPermissionId, + InvalidValidator +} from "../types/Error.sol"; import {ValidationId, ValidationType, ValidationMode} from "../types/Types.sol"; -import {VALIDATION_MANAGER_STORAGE_SLOT, VALIDATION_TYPE_ROOT,VALIDATION_TYPE_VALIDATOR,VALIDATION_TYPE_PERMISSION,ERC1271_MAGICVALUE} from "../types/Constants.sol"; +import { + VALIDATION_MANAGER_STORAGE_SLOT, + VALIDATION_TYPE_ROOT, + VALIDATION_TYPE_VALIDATOR, + VALIDATION_TYPE_PERMISSION, + ERC1271_MAGICVALUE +} from "../types/Constants.sol"; import {ValidationStorage, ValidationInfo, Install} from "../types/Structs.sol"; import {Lib4337} from "../lib/Lib4337.sol"; diff --git a/test/mock/MockERC721.sol b/test/mock/MockERC721.sol index 39b37abe..19b32255 100644 --- a/test/mock/MockERC721.sol +++ b/test/mock/MockERC721.sol @@ -16,6 +16,7 @@ contract MockERC721 is ERC721 { return "MOCK"; } /// forge-lint: disable-next-line(mixed-case-function) + function tokenURI(uint256) public pure override returns (string memory) { return ""; } From ef3cfe22bebf328d2b4b363e1c67136e3a83ae68 Mon Sep 17 00:00:00 2001 From: leekt Date: Mon, 29 Sep 2025 23:46:13 +0900 Subject: [PATCH 058/121] fmt --- test/Kernel7702.t.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Kernel7702.t.sol b/test/Kernel7702.t.sol index 3346cb65..8273c3f8 100644 --- a/test/Kernel7702.t.sol +++ b/test/Kernel7702.t.sol @@ -45,6 +45,6 @@ contract Kernel7702Test is KernelTest { function test_erc1271() external { bytes32 hash = bytes32(vm.randomBytes(32)); (uint8 v, bytes32 r, bytes32 s) = vm.sign(ownerKey, hash); - kernel.isValidSignature(hash, abi.encodePacked(r,s,v)); + kernel.isValidSignature(hash, abi.encodePacked(r, s, v)); } } From a8e064adeeb3f3d056de5913ee57fca3bb12f7b8 Mon Sep 17 00:00:00 2001 From: leekt Date: Mon, 6 Oct 2025 22:30:52 +0900 Subject: [PATCH 059/121] temp: remove mock contract eth --- test/mock/MockContractEth.sol | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 test/mock/MockContractEth.sol diff --git a/test/mock/MockContractEth.sol b/test/mock/MockContractEth.sol deleted file mode 100644 index eba33fac..00000000 --- a/test/mock/MockContractEth.sol +++ /dev/null @@ -1,11 +0,0 @@ -pragma solidity ^0.8.0; - -contract MockContractETH { - function useTransfer(address payable recipient, uint256 v) external { - recipient.transfer(v); - } - - function useSend(address payable recipient, uint256 v) external { - require(recipient.send(v), "send failed"); - } -} From b11d1e726ee709425af7b4716376fd2c2acc9854 Mon Sep 17 00:00:00 2001 From: leekt Date: Mon, 6 Oct 2025 22:31:30 +0900 Subject: [PATCH 060/121] fix: renamed MockContractEth to MockContractETH --- test/mock/MockContractETH.sol | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 test/mock/MockContractETH.sol diff --git a/test/mock/MockContractETH.sol b/test/mock/MockContractETH.sol new file mode 100644 index 00000000..eba33fac --- /dev/null +++ b/test/mock/MockContractETH.sol @@ -0,0 +1,11 @@ +pragma solidity ^0.8.0; + +contract MockContractETH { + function useTransfer(address payable recipient, uint256 v) external { + recipient.transfer(v); + } + + function useSend(address payable recipient, uint256 v) external { + require(recipient.send(v), "send failed"); + } +} From a8cec2cd6148ce7f8d04bd327794fca1b05c83a2 Mon Sep 17 00:00:00 2001 From: leekt Date: Mon, 29 Sep 2025 16:00:23 +0900 Subject: [PATCH 061/121] fix: initializer in kernel uups --- snapshots/Kernel7702Test.json | 2 +- snapshots/KernelECDSATest.json | 2 +- snapshots/KernelFactoryTest.json | 2 +- snapshots/KernelImmutableECDSATest.json | 2 +- snapshots/KernelTest.json | 2 +- src/Kernel.sol | 2 +- src/KernelImmutableECDSA.sol | 2 +- src/KernelUUPS.sol | 16 +++++++++++++++- 8 files changed, 22 insertions(+), 8 deletions(-) diff --git a/snapshots/Kernel7702Test.json b/snapshots/Kernel7702Test.json index 1038772c..1ab3c820 100644 --- a/snapshots/Kernel7702Test.json +++ b/snapshots/Kernel7702Test.json @@ -1,3 +1,3 @@ { - "Root - foo()": "168608" + "Root - foo()": "173183" } \ No newline at end of file diff --git a/snapshots/KernelECDSATest.json b/snapshots/KernelECDSATest.json index df696f33..d83121d3 100644 --- a/snapshots/KernelECDSATest.json +++ b/snapshots/KernelECDSATest.json @@ -1,3 +1,3 @@ { - "Root - foo()": "180217" + "Root - foo()": "186655" } \ No newline at end of file diff --git a/snapshots/KernelFactoryTest.json b/snapshots/KernelFactoryTest.json index 5f524074..cebeb695 100644 --- a/snapshots/KernelFactoryTest.json +++ b/snapshots/KernelFactoryTest.json @@ -1,3 +1,3 @@ { - "Mock - deploy()": "159102" + "Mock - deploy()": "188092" } \ No newline at end of file diff --git a/snapshots/KernelImmutableECDSATest.json b/snapshots/KernelImmutableECDSATest.json index ea876918..74fcc101 100644 --- a/snapshots/KernelImmutableECDSATest.json +++ b/snapshots/KernelImmutableECDSATest.json @@ -1,3 +1,3 @@ { - "Root - foo()": "171565" + "Root - foo()": "176320" } \ No newline at end of file diff --git a/snapshots/KernelTest.json b/snapshots/KernelTest.json index 2f7500b9..44deecc7 100644 --- a/snapshots/KernelTest.json +++ b/snapshots/KernelTest.json @@ -1,3 +1,3 @@ { - "Root - foo()": "194083" + "Root - foo()": "200530" } \ No newline at end of file diff --git a/src/Kernel.sol b/src/Kernel.sol index 31106d25..e35ba4ff 100644 --- a/src/Kernel.sol +++ b/src/Kernel.sol @@ -53,7 +53,7 @@ abstract contract Kernel is ModuleManager, ExecutionManager { bytes userOpSignature; } - function initialize(Install[] calldata packages) external { + function initialize(Install[] calldata packages) external virtual { require(!_initialized(), InvalidInitialization()); // this is initialize // require first package to be the root validator diff --git a/src/KernelImmutableECDSA.sol b/src/KernelImmutableECDSA.sol index aa397a8c..7f3bb9aa 100644 --- a/src/KernelImmutableECDSA.sol +++ b/src/KernelImmutableECDSA.sol @@ -25,7 +25,7 @@ contract KernelImmutableECDSA is KernelUUPS { return false; } - function _initialize(Install[] calldata packages) internal override initializer { + function _initialize(Install[] calldata packages) internal override { _install(packages); } } diff --git a/src/KernelUUPS.sol b/src/KernelUUPS.sol index 5236a13c..a337be51 100644 --- a/src/KernelUUPS.sol +++ b/src/KernelUUPS.sol @@ -2,13 +2,27 @@ pragma solidity ^0.8.0; import {IEntryPoint} from "account-abstraction/interfaces/IEntryPoint.sol"; import {Kernel} from "./Kernel.sol"; +import {Install} from "./types/Structs.sol"; import {UUPSUpgradeable} from "solady/utils/UUPSUpgradeable.sol"; import {Initializable} from "solady/utils/Initializable.sol"; contract KernelUUPS is Kernel, UUPSUpgradeable, Initializable { - constructor(IEntryPoint _entryPoint) Kernel(_entryPoint) {} + constructor(IEntryPoint _entryPoint) Kernel(_entryPoint) { + _disableInitializers(); + } + + function initialize(Install[] calldata packages) external override initializer { + require(!_initialized(), InvalidInitialization()); + // this is initialize + // require first package to be the root validator + _initialize(packages); + } function _authorizeUpgrade(address) internal override { _onlyEntryPointOrSelf(); } + + function _statefulInitializeCheck() internal view override returns(bool) { + return super._statefulInitializeCheck(); + } } From 4557481c476b6a70430289e5bcc8214695ae5eeb Mon Sep 17 00:00:00 2001 From: leekt Date: Mon, 29 Sep 2025 16:00:52 +0900 Subject: [PATCH 062/121] fmt --- src/KernelUUPS.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/KernelUUPS.sol b/src/KernelUUPS.sol index a337be51..37b36b47 100644 --- a/src/KernelUUPS.sol +++ b/src/KernelUUPS.sol @@ -10,7 +10,7 @@ contract KernelUUPS is Kernel, UUPSUpgradeable, Initializable { constructor(IEntryPoint _entryPoint) Kernel(_entryPoint) { _disableInitializers(); } - + function initialize(Install[] calldata packages) external override initializer { require(!_initialized(), InvalidInitialization()); // this is initialize @@ -22,7 +22,7 @@ contract KernelUUPS is Kernel, UUPSUpgradeable, Initializable { _onlyEntryPointOrSelf(); } - function _statefulInitializeCheck() internal view override returns(bool) { + function _statefulInitializeCheck() internal view override returns (bool) { return super._statefulInitializeCheck(); } } From 3937389bb9a22c2e9ddeaa309007e48ca566b05d Mon Sep 17 00:00:00 2001 From: leekt Date: Mon, 29 Sep 2025 16:49:59 +0900 Subject: [PATCH 063/121] test: added initialize revert test --- test/Kernel.t.sol | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/test/Kernel.t.sol b/test/Kernel.t.sol index bfce9705..e5620a5a 100644 --- a/test/Kernel.t.sol +++ b/test/Kernel.t.sol @@ -33,10 +33,12 @@ contract KernelTest is KernelSelectorTest, KernelHookTest { + KernelUUPS uups; + function setUp() external { ep = EntryPointLib.deploy(); - KernelUUPS uups = new KernelUUPS(ep); + uups = new KernelUUPS(ep); KernelImmutableECDSA immutableEcdsa = new KernelImmutableECDSA(ep); factory = new KernelFactory(uups, immutableEcdsa); helper = new KernelHelper(); @@ -52,6 +54,15 @@ contract KernelTest is _initialize(); } + function test_implementation_revert_on_initialize() external { + rootValidator = new MockValidator(); + rootValidatorData = hex""; + Install[] memory pkgs = new Install[](1); + pkgs[0] = Install({moduleType: 1, module: address(rootValidator), moduleData: hex"", internalData: hex""}); + vm.expectRevert(); + uups.initialize(pkgs); + } + function _initialize() internal virtual override { rootValidator = new MockValidator(); rootValidatorData = hex""; From 041bb87d59dd6d5fb390fe0a1a4aecd5271359d8 Mon Sep 17 00:00:00 2001 From: leekt Date: Mon, 6 Oct 2025 22:25:13 +0900 Subject: [PATCH 064/121] fix: removed meaningless codes --- snapshots/Kernel7702Test.json | 2 +- snapshots/KernelECDSATest.json | 2 +- snapshots/KernelFactoryTest.json | 2 +- snapshots/KernelImmutableECDSATest.json | 2 +- snapshots/KernelTest.json | 2 +- src/KernelUUPS.sol | 5 ----- 6 files changed, 5 insertions(+), 10 deletions(-) diff --git a/snapshots/Kernel7702Test.json b/snapshots/Kernel7702Test.json index 1ab3c820..1038772c 100644 --- a/snapshots/Kernel7702Test.json +++ b/snapshots/Kernel7702Test.json @@ -1,3 +1,3 @@ { - "Root - foo()": "173183" + "Root - foo()": "168608" } \ No newline at end of file diff --git a/snapshots/KernelECDSATest.json b/snapshots/KernelECDSATest.json index d83121d3..df696f33 100644 --- a/snapshots/KernelECDSATest.json +++ b/snapshots/KernelECDSATest.json @@ -1,3 +1,3 @@ { - "Root - foo()": "186655" + "Root - foo()": "180217" } \ No newline at end of file diff --git a/snapshots/KernelFactoryTest.json b/snapshots/KernelFactoryTest.json index cebeb695..68737a6f 100644 --- a/snapshots/KernelFactoryTest.json +++ b/snapshots/KernelFactoryTest.json @@ -1,3 +1,3 @@ { - "Mock - deploy()": "188092" + "Mock - deploy()": "181649" } \ No newline at end of file diff --git a/snapshots/KernelImmutableECDSATest.json b/snapshots/KernelImmutableECDSATest.json index 74fcc101..ea876918 100644 --- a/snapshots/KernelImmutableECDSATest.json +++ b/snapshots/KernelImmutableECDSATest.json @@ -1,3 +1,3 @@ { - "Root - foo()": "176320" + "Root - foo()": "171565" } \ No newline at end of file diff --git a/snapshots/KernelTest.json b/snapshots/KernelTest.json index 44deecc7..2f7500b9 100644 --- a/snapshots/KernelTest.json +++ b/snapshots/KernelTest.json @@ -1,3 +1,3 @@ { - "Root - foo()": "200530" + "Root - foo()": "194083" } \ No newline at end of file diff --git a/src/KernelUUPS.sol b/src/KernelUUPS.sol index 37b36b47..0f453dd0 100644 --- a/src/KernelUUPS.sol +++ b/src/KernelUUPS.sol @@ -12,7 +12,6 @@ contract KernelUUPS is Kernel, UUPSUpgradeable, Initializable { } function initialize(Install[] calldata packages) external override initializer { - require(!_initialized(), InvalidInitialization()); // this is initialize // require first package to be the root validator _initialize(packages); @@ -21,8 +20,4 @@ contract KernelUUPS is Kernel, UUPSUpgradeable, Initializable { function _authorizeUpgrade(address) internal override { _onlyEntryPointOrSelf(); } - - function _statefulInitializeCheck() internal view override returns (bool) { - return super._statefulInitializeCheck(); - } } From a220cf9509374bcc2df7ebef9024b69d8962aa31 Mon Sep 17 00:00:00 2001 From: leekt Date: Mon, 29 Sep 2025 14:55:27 +0900 Subject: [PATCH 065/121] code separation done --- .gitmodules | 3 ++ foundry.lock | 14 ++++++ foundry.toml | 6 +++ lib/halmos-cheatcodes | 1 + snapshots/Kernel7702Test.json | 2 +- snapshots/KernelECDSATest.json | 2 +- snapshots/KernelFactoryTest.json | 2 +- snapshots/KernelImmutableECDSATest.json | 2 +- snapshots/KernelTest.json | 2 +- src/Kernel.sol | 27 +++++++---- src/core/ExecutionManager.sol | 18 +++++--- test/Kernel.t.sol | 1 - test/Kernel7702.t.sol | 2 +- test/KernelERC1271Test.sol | 32 +++++++------ test/KernelExecuteTest.sol | 12 +++++ test/KernelExecutorTest.sol | 1 + test/halmos/KernelExecutorHalmos.t.sol | 61 +++++++++++++++++++++++++ test/mock/MockCallee.sol | 4 ++ test/mock/MockExecutor.sol | 7 ++- 19 files changed, 160 insertions(+), 39 deletions(-) create mode 100644 foundry.lock create mode 160000 lib/halmos-cheatcodes create mode 100644 test/halmos/KernelExecutorHalmos.t.sol diff --git a/.gitmodules b/.gitmodules index c73a09c3..a65a2247 100644 --- a/.gitmodules +++ b/.gitmodules @@ -8,3 +8,6 @@ [submodule "lib/solady"] path = lib/solady url = https://github.com/vectorized/solady +[submodule "lib/halmos-cheatcodes"] + path = lib/halmos-cheatcodes + url = https://github.com/a16z/halmos-cheatcodes diff --git a/foundry.lock b/foundry.lock new file mode 100644 index 00000000..2a76b545 --- /dev/null +++ b/foundry.lock @@ -0,0 +1,14 @@ +{ + "lib/solady": { + "rev": "b609a9c79ce541c2beca7a7d247665e7c93942a3" + }, + "lib/account-abstraction": { + "branch": { + "name": "develop", + "rev": "cc3893bcaf2272c163ce89d5eb9eadb8e6b52db7" + } + }, + "lib/forge-std": { + "rev": "f46d8301cf732f4f83846565aa475628265e51e0" + } +} \ No newline at end of file diff --git a/foundry.toml b/foundry.toml index ef066e4f..3a5ba691 100644 --- a/foundry.toml +++ b/foundry.toml @@ -7,4 +7,10 @@ optimizer = true run = 200 evm_version = 'prague' +extra_output = ["storageLayout"] # See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options + +[invariant] +runs = 1000 +depth = 1000 + diff --git a/lib/halmos-cheatcodes b/lib/halmos-cheatcodes new file mode 160000 index 00000000..6da4e692 --- /dev/null +++ b/lib/halmos-cheatcodes @@ -0,0 +1 @@ +Subproject commit 6da4e692c357ba6d641a2e677a28298cac9f76ab diff --git a/snapshots/Kernel7702Test.json b/snapshots/Kernel7702Test.json index 1038772c..71fd26ae 100644 --- a/snapshots/Kernel7702Test.json +++ b/snapshots/Kernel7702Test.json @@ -1,3 +1,3 @@ { - "Root - foo()": "168608" + "Root - foo()": "168876" } \ No newline at end of file diff --git a/snapshots/KernelECDSATest.json b/snapshots/KernelECDSATest.json index df696f33..31f519de 100644 --- a/snapshots/KernelECDSATest.json +++ b/snapshots/KernelECDSATest.json @@ -1,3 +1,3 @@ { - "Root - foo()": "180217" + "Root - foo()": "180486" } \ No newline at end of file diff --git a/snapshots/KernelFactoryTest.json b/snapshots/KernelFactoryTest.json index 5f524074..4a21e75b 100644 --- a/snapshots/KernelFactoryTest.json +++ b/snapshots/KernelFactoryTest.json @@ -1,3 +1,3 @@ { - "Mock - deploy()": "159102" + "Mock - deploy()": "159106" } \ No newline at end of file diff --git a/snapshots/KernelImmutableECDSATest.json b/snapshots/KernelImmutableECDSATest.json index ea876918..f39af0f9 100644 --- a/snapshots/KernelImmutableECDSATest.json +++ b/snapshots/KernelImmutableECDSATest.json @@ -1,3 +1,3 @@ { - "Root - foo()": "171565" + "Root - foo()": "171834" } \ No newline at end of file diff --git a/snapshots/KernelTest.json b/snapshots/KernelTest.json index 2f7500b9..7bf5ac5e 100644 --- a/snapshots/KernelTest.json +++ b/snapshots/KernelTest.json @@ -1,3 +1,3 @@ { - "Root - foo()": "194083" + "Root - foo()": "194352" } \ No newline at end of file diff --git a/src/Kernel.sol b/src/Kernel.sol index 31106d25..0abb0d54 100644 --- a/src/Kernel.sol +++ b/src/Kernel.sol @@ -3,10 +3,12 @@ pragma solidity ^0.8.0; import {IEntryPoint} from "account-abstraction/interfaces/IEntryPoint.sol"; import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; import {IExecutor, IHook} from "./interfaces/IERC7579Modules.sol"; +import {IERC7579Account} from "./interfaces/IERC7579Account.sol"; import {ModuleManager, Install} from "./core/ModuleManager.sol"; import {parseNonce} from "./core/ValidationManager.sol"; import {ExecutionManager} from "./core/ExecutionManager.sol"; import {Lib4337} from "./lib/Lib4337.sol"; +import {ERC1271} from "./lib/ERC1271.sol"; import {LibERC7579} from "solady/accounts/LibERC7579.sol"; import { CallType, @@ -29,7 +31,7 @@ import {Received} from "./types/Events.sol"; import {VALIDATION_TYPE_ROOT} from "./types/Constants.sol"; import {ValidationStorage, ValidationInfo} from "./types/Structs.sol"; -abstract contract Kernel is ModuleManager, ExecutionManager { +abstract contract Kernel is ModuleManager, ExecutionManager, IERC7579Account { IEntryPoint immutable ENTRYPOINT; function _onlyEntryPointOrSelf() internal { @@ -82,6 +84,10 @@ abstract contract Kernel is ModuleManager, ExecutionManager { } } + function isValidSignature(bytes32 hash, bytes calldata signature) public view override(ERC1271, IERC7579Account) returns(bytes4) { + return ERC1271.isValidSignature(hash, signature); + } + function _processUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash) internal returns (uint256 validationData) @@ -145,13 +151,13 @@ abstract contract Kernel is ModuleManager, ExecutionManager { _execute(mode, executionData); } - function executeFromExecutor(bytes32 mode, bytes calldata executionData) external payable { + function executeFromExecutor(bytes32 mode, bytes calldata executionData) external payable returns (bytes[] memory returnData){ _verifyExecutionData(mode, executionData); - _executeFromExecutor(mode, executionData); + return _executeFromExecutor(mode, executionData); } - function _executeFromExecutor(bytes32 mode, bytes calldata executionData) internal executorHook { - _execute(mode, executionData); + function _executeFromExecutor(bytes32 mode, bytes calldata executionData) internal executorHook returns(bytes[] memory retyrbData) { + return _execute(mode, executionData); } function _fallback() internal returns (bytes memory res) { @@ -213,7 +219,7 @@ abstract contract Kernel is ModuleManager, ExecutionManager { _setValidNonceFrom(seq); } - function installModule(uint256 moduleType, address module, bytes calldata initData) external payable { + function installModule(uint256 moduleType, address module, bytes calldata initData) external payable override { _onlyEntryPointOrSelf(); InstallModuleDataFormat calldata imdf; assembly { @@ -222,7 +228,7 @@ abstract contract Kernel is ModuleManager, ExecutionManager { _installModule(moduleType, module, imdf.installData, imdf.internalData); } - function uninstallModule(uint256 moduleType, address module, bytes calldata initData) external payable { + function uninstallModule(uint256 moduleType, address module, bytes calldata initData) external payable override { _onlyEntryPointOrSelf(); InstallModuleDataFormat calldata imdf; assembly { @@ -253,7 +259,7 @@ abstract contract Kernel is ModuleManager, ExecutionManager { emit Received(msg.sender, msg.value); } - function supportsExecutionMode(bytes32 mode) external pure returns (bool) { + function supportsExecutionMode(bytes32 mode) external override pure returns (bool) { bytes1 callType = LibERC7579.getCallType(mode); bytes1 execType = LibERC7579.getExecType(mode); if (!(execType == LibERC7579.EXECTYPE_DEFAULT || execType == LibERC7579.EXECTYPE_TRY)) { @@ -270,13 +276,14 @@ abstract contract Kernel is ModuleManager, ExecutionManager { return true; } - function supportsModule(uint256 moduleTypeId) external pure returns (bool) { + function supportsModule(uint256 moduleTypeId) external override pure returns (bool) { return moduleTypeId < 7; } function isModuleInstalled(uint256 moduleTypeId, address module, bytes calldata additionalContext) external view + override returns (bool) { if (moduleTypeId == 1) { @@ -307,7 +314,7 @@ abstract contract Kernel is ModuleManager, ExecutionManager { } } - function accountId() external pure returns (string memory accountImplementationId) { + function accountId() external pure override returns (string memory accountImplementationId) { return "kernel.v0.4"; } } diff --git a/src/core/ExecutionManager.sol b/src/core/ExecutionManager.sol index ef85c4d4..7215487e 100644 --- a/src/core/ExecutionManager.sol +++ b/src/core/ExecutionManager.sol @@ -4,7 +4,7 @@ import {LibERC7579} from "solady/accounts/LibERC7579.sol"; import {InvalidExecType, InvalidCallType} from "../types/Error.sol"; abstract contract ExecutionManager { - function _execute(bytes32 mode, bytes calldata executionData) internal { + function _execute(bytes32 mode, bytes calldata executionData) internal returns(bytes[] memory) { bytes1 callType = LibERC7579.getCallType(mode); bytes1 execType = LibERC7579.getExecType(mode); function() onRevert; @@ -16,7 +16,7 @@ abstract contract ExecutionManager { revert InvalidExecType(); } - function(bytes calldata, function()) executeFunction; + function(bytes calldata, function()) returns(bytes[] memory) executeFunction; if (callType == LibERC7579.CALLTYPE_SINGLE) { executeFunction = _executeCall; } else if (callType == LibERC7579.CALLTYPE_BATCH) { @@ -26,29 +26,33 @@ abstract contract ExecutionManager { } else { revert InvalidCallType(); } - executeFunction(executionData, onRevert); + return executeFunction(executionData, onRevert); } - function _executeCall(bytes calldata executionData, function() onRevert) internal { + function _executeCall(bytes calldata executionData, function() onRevert) internal returns(bytes[] memory results){ (address target, uint256 value, bytes calldata data) = LibERC7579.decodeSingle(executionData); bool success = _call(target, value, data); if (!success) { onRevert(); } + results = new bytes[](1); + results[0] = _getReturn(); } - function _executeDelegateCall(bytes calldata executionData, function() onRevert) internal { + function _executeDelegateCall(bytes calldata executionData, function() onRevert) internal returns(bytes[] memory results){ (address delegate, bytes calldata data) = LibERC7579.decodeDelegate(executionData); bool success = _delegateCall(delegate, data); if (!success) { onRevert(); } + results = new bytes[](1); + results[0] = _getReturn(); } - function _executeBatchCall(bytes calldata executionData, function() onRevert) internal { + function _executeBatchCall(bytes calldata executionData, function() onRevert) internal returns(bytes[] memory results){ bytes32[] calldata pointers = LibERC7579.decodeBatch(executionData); uint256 length = pointers.length; - bytes[] memory result = new bytes[](length); + results = new bytes[](length); unchecked { for (uint256 i; i < length; i++) { (address target, uint256 value, bytes calldata data) = LibERC7579.getExecution(pointers, i); diff --git a/test/Kernel.t.sol b/test/Kernel.t.sol index bfce9705..82dfc873 100644 --- a/test/Kernel.t.sol +++ b/test/Kernel.t.sol @@ -48,7 +48,6 @@ contract KernelTest is policy = new MockPolicy(); signer = new MockSigner(); permissionId = bytes20(keccak256(abi.encodePacked("Hello world"))); - vm.txGasPrice(1); _initialize(); } diff --git a/test/Kernel7702.t.sol b/test/Kernel7702.t.sol index 8273c3f8..da354961 100644 --- a/test/Kernel7702.t.sol +++ b/test/Kernel7702.t.sol @@ -42,7 +42,7 @@ contract Kernel7702Test is KernelTest { return abi.encodePacked(r, s, v); } - function test_erc1271() external { + function test_erc1271() external erc1271Test { bytes32 hash = bytes32(vm.randomBytes(32)); (uint8 v, bytes32 r, bytes32 s) = vm.sign(ownerKey, hash); kernel.isValidSignature(hash, abi.encodePacked(r, s, v)); diff --git a/test/KernelERC1271Test.sol b/test/KernelERC1271Test.sol index badfd9da..f0041528 100644 --- a/test/KernelERC1271Test.sol +++ b/test/KernelERC1271Test.sol @@ -5,14 +5,18 @@ import {ERC1271_MAGICVALUE, ERC1271_INVALID} from "src/types/Constants.sol"; import {KernelTestBase} from "./KernelTestBase.sol"; abstract contract KernelERC1271Test is KernelTestBase { - function test_erc7739() public { + modifier erc1271Test { + vm.txGasPrice(1); + _; + } + function test_erc7739() public erc1271Test { assertEq( kernel.isValidSignature(0x7739773977397739773977397739773977397739773977397739773977397739, ""), bytes4(0x77390001) ); } - function test_erc1271_root() external unitTest { + function test_erc1271_root() external unitTest erc1271Test { bytes32 messageHash = keccak256("Hello world"); (bytes32 contentsHash, bytes memory sig) = _erc1271Signature(messageHash, "C(bytes32 stuff)", "", _rootSignHash, false, true); @@ -20,7 +24,7 @@ abstract contract KernelERC1271Test is KernelTestBase { assertEq(ret, ERC1271_MAGICVALUE); } - function test_erc1271_fail_invalid() external unitTest { + function test_erc1271_fail_invalid() external unitTest erc1271Test { bytes32 messageHash = keccak256("Hello world"); (bytes32 contentsHash, bytes memory sig) = _erc1271Signature(messageHash, "C(bytes32 stuff)", "", _rootSignHash, false, true); @@ -29,7 +33,7 @@ abstract contract KernelERC1271Test is KernelTestBase { assertEq(ret, ERC1271_INVALID); } - function test_erc1271_root_fail() external unitTest { + function test_erc1271_root_fail() external unitTest erc1271Test { bytes32 messageHash = keccak256("Hello world"); (bytes32 contentsHash, bytes memory sig) = _erc1271Signature(messageHash, "C(bytes32 stuff)", "", _rootSignHash, false, false); @@ -37,7 +41,7 @@ abstract contract KernelERC1271Test is KernelTestBase { assertEq(ret, ERC1271_INVALID); } - function test_erc1271_root_personal_sign() external unitTest { + function test_erc1271_root_personal_sign() external unitTest erc1271Test { bytes32 messageHash = keccak256("Hello world"); bytes32 personalHash = _toErc1271HashPersonalSign(messageHash); bytes memory sig = _rootSignHash(personalHash, true); @@ -45,7 +49,7 @@ abstract contract KernelERC1271Test is KernelTestBase { assertEq(ret, ERC1271_MAGICVALUE); } - function test_erc1271_root_personal_sign_fail() external unitTest { + function test_erc1271_root_personal_sign_fail() external unitTest erc1271Test { bytes32 messageHash = keccak256("Hello world"); bytes32 personalHash = _toErc1271HashPersonalSign(messageHash); bytes memory sig = _rootSignHash(personalHash, false); @@ -53,7 +57,7 @@ abstract contract KernelERC1271Test is KernelTestBase { assertEq(ret, ERC1271_INVALID); } - function test_erc1271_validator() external unitTest { + function test_erc1271_validator() external unitTest erc1271Test { bytes32 messageHash = keccak256("Hello world"); (bytes32 contentsHash, bytes memory sig) = _erc1271Signature(messageHash, "C(bytes32 stuff)", "", _validatorSignHash, false, true); @@ -64,7 +68,7 @@ abstract contract KernelERC1271Test is KernelTestBase { assertEq(ret, ERC1271_MAGICVALUE); } - function test_erc1271_validator_fail() external unitTest { + function test_erc1271_validator_fail() external unitTest erc1271Test { bytes32 messageHash = keccak256("Hello world"); (bytes32 contentsHash, bytes memory sig) = _erc1271Signature(messageHash, "C(bytes32 stuff)", "", _validatorSignHash, false, false); @@ -75,7 +79,7 @@ abstract contract KernelERC1271Test is KernelTestBase { assertEq(ret, ERC1271_INVALID); } - function test_erc1271_validator_personal_sign() external unitTest { + function test_erc1271_validator_personal_sign() external unitTest erc1271Test { bytes32 messageHash = keccak256("Hello world"); bytes32 personalHash = _toErc1271HashPersonalSign(messageHash); bytes memory sig = _validatorSignHash(personalHash, true); @@ -84,7 +88,7 @@ abstract contract KernelERC1271Test is KernelTestBase { assertEq(ret, ERC1271_MAGICVALUE); } - function test_erc1271_validator_personal_sign_fail() external unitTest { + function test_erc1271_validator_personal_sign_fail() external unitTest erc1271Test { bytes32 messageHash = keccak256("Hello world"); bytes32 personalHash = _toErc1271HashPersonalSign(messageHash); bytes memory sig = _validatorSignHash(personalHash, false); @@ -93,7 +97,7 @@ abstract contract KernelERC1271Test is KernelTestBase { assertEq(ret, ERC1271_INVALID); } - function test_erc1271_permission() external unitTest { + function test_erc1271_permission() external unitTest erc1271Test{ bytes32 messageHash = keccak256("Hello world"); (bytes32 contentsHash, bytes memory sig) = _erc1271Signature(messageHash, "C(bytes32 stuff)", "", _permissionSignHash, false, true); @@ -103,7 +107,7 @@ abstract contract KernelERC1271Test is KernelTestBase { assertEq(ret, ERC1271_MAGICVALUE); } - function test_erc1271_permission_fail() external unitTest { + function test_erc1271_permission_fail() external unitTest erc1271Test { bytes32 messageHash = keccak256("Hello world"); (bytes32 contentsHash, bytes memory sig) = _erc1271Signature(messageHash, "C(bytes32 stuff)", "", _permissionSignHash, false, false); @@ -113,7 +117,7 @@ abstract contract KernelERC1271Test is KernelTestBase { assertEq(ret, ERC1271_INVALID); } - function test_erc1271_permission_personal_sign() external unitTest { + function test_erc1271_permission_personal_sign() external unitTest erc1271Test { bytes32 messageHash = keccak256("Hello world"); bytes32 personalHash = _toErc1271HashPersonalSign(messageHash); bytes memory sig = _permissionSignHash(personalHash, true); @@ -123,7 +127,7 @@ abstract contract KernelERC1271Test is KernelTestBase { assertEq(ret, ERC1271_MAGICVALUE); } - function test_erc1271_permission_personal_sign_fail() external unitTest { + function test_erc1271_permission_personal_sign_fail() external unitTest erc1271Test { bytes32 messageHash = keccak256("Hello world"); bytes32 personalHash = _toErc1271HashPersonalSign(messageHash); bytes memory sig = _permissionSignHash(personalHash, false); diff --git a/test/KernelExecuteTest.sol b/test/KernelExecuteTest.sol index 7a52dad6..3da25f62 100644 --- a/test/KernelExecuteTest.sol +++ b/test/KernelExecuteTest.sol @@ -114,4 +114,16 @@ abstract contract KernelExecuteTest is KernelTestBase { abi.encodePacked(address(callee), abi.encodeWithSelector(MockCallee.forceRevert.selector)) ); } + + function test_execute_from_executor_return_data() external { + bytes memory data = hex"deadbeef"; + vm.startPrank(executor); + bytes[] memory ret = kernel.executeFromExecutor( + bytes32(0), abi.encodePacked(address(callee), uint256(0), abi.encodeWithSelector(MockCallee.ret.selector, data)) + ); + assertEq(ret.length, 1); + bytes memory actual = abi.decode(ret[0], (bytes)); + assertEq(keccak256(actual), keccak256(data)); + } + } diff --git a/test/KernelExecutorTest.sol b/test/KernelExecutorTest.sol index 1a47ed95..51cbd050 100644 --- a/test/KernelExecutorTest.sol +++ b/test/KernelExecutorTest.sol @@ -49,6 +49,7 @@ abstract contract KernelExecutorTest is KernelTestBase { assertEq(callee.bar(), 1); } + function test_execute_batch_from_executor() external unitTestExecutor { Call[] memory calls = new Call[](2); calls[0] = Call({to: address(callee), value: 0, data: abi.encodeWithSelector(MockCallee.foo.selector)}); diff --git a/test/halmos/KernelExecutorHalmos.t.sol b/test/halmos/KernelExecutorHalmos.t.sol new file mode 100644 index 00000000..27c76fc6 --- /dev/null +++ b/test/halmos/KernelExecutorHalmos.t.sol @@ -0,0 +1,61 @@ +pragma solidity ^0.8.0; +import {Test} from "forge-std/Test.sol"; +import {SymTest} from "halmos-cheatcodes/SymTest.sol"; +import {MockCallee} from "../mock/MockCallee.sol"; +import {KernelUUPS} from "src/KernelUUPS.sol"; +import {IEntryPoint} from "account-abstraction/interfaces/IEntryPoint.sol"; + +contract KernelExecutorHalmos is SymTest, Test { + MockCallee callee; + KernelUUPS kernel; + address executor; + + function setUp() external { + callee = new MockCallee(); + address entryPoint = makeAddr("EntryPoint"); + kernel = new KernelUUPS(IEntryPoint(entryPoint)); + executor = address(0xdeadbeef); + vm.startPrank(entryPoint); + kernel.installModule(2, executor, abi.encode(hex"", "")); + vm.stopPrank(); + } + + function check_execute_from_executor_return0() external { + execute_from_executor(0); + } + + function check_execute_from_executor_return8() external { + execute_from_executor(8); + } + + function check_execute_from_executor_return32() external { + execute_from_executor(32); + } + + function check_execute_from_executor_return64() external { + execute_from_executor(64); + } + + function check_execute_from_executor_return256() external { + execute_from_executor(256); + } + + function check_execute_from_executor_return1024() external { + execute_from_executor(1024); + } + + function check_execute_from_executor_return4096() external { + execute_from_executor(4096); + } + + function execute_from_executor(uint256 length) internal { + bytes memory data = svm.createBytes(length, 'data'); + vm.startPrank(executor); + bytes[] memory ret = kernel.executeFromExecutor( + bytes32(0), abi.encodePacked(address(callee), uint256(0), abi.encodeWithSelector(MockCallee.ret.selector, data)) + ); + assertEq(ret.length, 1); + bytes memory actual = abi.decode(ret[0], (bytes)); + assertEq(keccak256(actual), keccak256(data)); + } +} diff --git a/test/mock/MockCallee.sol b/test/mock/MockCallee.sol index cbf01d81..04d41f44 100644 --- a/test/mock/MockCallee.sol +++ b/test/mock/MockCallee.sol @@ -20,4 +20,8 @@ contract MockCallee { function forceRevert() external { revert Haha(); } + + function ret(bytes memory dat) external pure returns(bytes memory) { + return dat; + } } diff --git a/test/mock/MockExecutor.sol b/test/mock/MockExecutor.sol index 64eff851..cdf2caf2 100644 --- a/test/mock/MockExecutor.sol +++ b/test/mock/MockExecutor.sol @@ -7,6 +7,8 @@ import {IERC7579Account} from "src/interfaces/IERC7579Account.sol"; contract MockExecutor is IExecutor { mapping(address => bytes) public data; + event Results(uint256 index, bytes result); + function onInstall(bytes calldata _data) external payable override { data[msg.sender] = _data; } @@ -24,6 +26,9 @@ contract MockExecutor is IExecutor { } function sudoDoExec(IERC7579Account account, bytes32 mode, bytes calldata executionCalldata) external payable { - account.executeFromExecutor(mode, executionCalldata); + bytes[] memory results = account.executeFromExecutor(mode, executionCalldata); + for(uint256 i = 0; i Date: Mon, 29 Sep 2025 14:55:36 +0900 Subject: [PATCH 066/121] fmt --- src/Kernel.sol | 23 ++++++++++++++++++----- src/core/ExecutionManager.sol | 17 +++++++++++++---- test/KernelERC1271Test.sol | 5 +++-- test/KernelExecuteTest.sol | 6 +++--- test/KernelExecutorTest.sol | 1 - test/halmos/KernelExecutorHalmos.t.sol | 22 ++++++++++++---------- test/mock/MockCallee.sol | 2 +- test/mock/MockExecutor.sol | 2 +- 8 files changed, 51 insertions(+), 27 deletions(-) diff --git a/src/Kernel.sol b/src/Kernel.sol index 0abb0d54..30fd5ce9 100644 --- a/src/Kernel.sol +++ b/src/Kernel.sol @@ -84,7 +84,12 @@ abstract contract Kernel is ModuleManager, ExecutionManager, IERC7579Account { } } - function isValidSignature(bytes32 hash, bytes calldata signature) public view override(ERC1271, IERC7579Account) returns(bytes4) { + function isValidSignature(bytes32 hash, bytes calldata signature) + public + view + override(ERC1271, IERC7579Account) + returns (bytes4) + { return ERC1271.isValidSignature(hash, signature); } @@ -151,12 +156,20 @@ abstract contract Kernel is ModuleManager, ExecutionManager, IERC7579Account { _execute(mode, executionData); } - function executeFromExecutor(bytes32 mode, bytes calldata executionData) external payable returns (bytes[] memory returnData){ + function executeFromExecutor(bytes32 mode, bytes calldata executionData) + external + payable + returns (bytes[] memory returnData) + { _verifyExecutionData(mode, executionData); return _executeFromExecutor(mode, executionData); } - function _executeFromExecutor(bytes32 mode, bytes calldata executionData) internal executorHook returns(bytes[] memory retyrbData) { + function _executeFromExecutor(bytes32 mode, bytes calldata executionData) + internal + executorHook + returns (bytes[] memory retyrbData) + { return _execute(mode, executionData); } @@ -259,7 +272,7 @@ abstract contract Kernel is ModuleManager, ExecutionManager, IERC7579Account { emit Received(msg.sender, msg.value); } - function supportsExecutionMode(bytes32 mode) external override pure returns (bool) { + function supportsExecutionMode(bytes32 mode) external pure override returns (bool) { bytes1 callType = LibERC7579.getCallType(mode); bytes1 execType = LibERC7579.getExecType(mode); if (!(execType == LibERC7579.EXECTYPE_DEFAULT || execType == LibERC7579.EXECTYPE_TRY)) { @@ -276,7 +289,7 @@ abstract contract Kernel is ModuleManager, ExecutionManager, IERC7579Account { return true; } - function supportsModule(uint256 moduleTypeId) external override pure returns (bool) { + function supportsModule(uint256 moduleTypeId) external pure override returns (bool) { return moduleTypeId < 7; } diff --git a/src/core/ExecutionManager.sol b/src/core/ExecutionManager.sol index 7215487e..26b2fef2 100644 --- a/src/core/ExecutionManager.sol +++ b/src/core/ExecutionManager.sol @@ -4,7 +4,7 @@ import {LibERC7579} from "solady/accounts/LibERC7579.sol"; import {InvalidExecType, InvalidCallType} from "../types/Error.sol"; abstract contract ExecutionManager { - function _execute(bytes32 mode, bytes calldata executionData) internal returns(bytes[] memory) { + function _execute(bytes32 mode, bytes calldata executionData) internal returns (bytes[] memory) { bytes1 callType = LibERC7579.getCallType(mode); bytes1 execType = LibERC7579.getExecType(mode); function() onRevert; @@ -29,7 +29,10 @@ abstract contract ExecutionManager { return executeFunction(executionData, onRevert); } - function _executeCall(bytes calldata executionData, function() onRevert) internal returns(bytes[] memory results){ + function _executeCall(bytes calldata executionData, function() onRevert) + internal + returns (bytes[] memory results) + { (address target, uint256 value, bytes calldata data) = LibERC7579.decodeSingle(executionData); bool success = _call(target, value, data); if (!success) { @@ -39,7 +42,10 @@ abstract contract ExecutionManager { results[0] = _getReturn(); } - function _executeDelegateCall(bytes calldata executionData, function() onRevert) internal returns(bytes[] memory results){ + function _executeDelegateCall(bytes calldata executionData, function() onRevert) + internal + returns (bytes[] memory results) + { (address delegate, bytes calldata data) = LibERC7579.decodeDelegate(executionData); bool success = _delegateCall(delegate, data); if (!success) { @@ -49,7 +55,10 @@ abstract contract ExecutionManager { results[0] = _getReturn(); } - function _executeBatchCall(bytes calldata executionData, function() onRevert) internal returns(bytes[] memory results){ + function _executeBatchCall(bytes calldata executionData, function() onRevert) + internal + returns (bytes[] memory results) + { bytes32[] calldata pointers = LibERC7579.decodeBatch(executionData); uint256 length = pointers.length; results = new bytes[](length); diff --git a/test/KernelERC1271Test.sol b/test/KernelERC1271Test.sol index f0041528..e32316bb 100644 --- a/test/KernelERC1271Test.sol +++ b/test/KernelERC1271Test.sol @@ -5,10 +5,11 @@ import {ERC1271_MAGICVALUE, ERC1271_INVALID} from "src/types/Constants.sol"; import {KernelTestBase} from "./KernelTestBase.sol"; abstract contract KernelERC1271Test is KernelTestBase { - modifier erc1271Test { + modifier erc1271Test() { vm.txGasPrice(1); _; } + function test_erc7739() public erc1271Test { assertEq( kernel.isValidSignature(0x7739773977397739773977397739773977397739773977397739773977397739, ""), @@ -97,7 +98,7 @@ abstract contract KernelERC1271Test is KernelTestBase { assertEq(ret, ERC1271_INVALID); } - function test_erc1271_permission() external unitTest erc1271Test{ + function test_erc1271_permission() external unitTest erc1271Test { bytes32 messageHash = keccak256("Hello world"); (bytes32 contentsHash, bytes memory sig) = _erc1271Signature(messageHash, "C(bytes32 stuff)", "", _permissionSignHash, false, true); diff --git a/test/KernelExecuteTest.sol b/test/KernelExecuteTest.sol index 3da25f62..dc9771d5 100644 --- a/test/KernelExecuteTest.sol +++ b/test/KernelExecuteTest.sol @@ -114,16 +114,16 @@ abstract contract KernelExecuteTest is KernelTestBase { abi.encodePacked(address(callee), abi.encodeWithSelector(MockCallee.forceRevert.selector)) ); } - + function test_execute_from_executor_return_data() external { bytes memory data = hex"deadbeef"; vm.startPrank(executor); bytes[] memory ret = kernel.executeFromExecutor( - bytes32(0), abi.encodePacked(address(callee), uint256(0), abi.encodeWithSelector(MockCallee.ret.selector, data)) + bytes32(0), + abi.encodePacked(address(callee), uint256(0), abi.encodeWithSelector(MockCallee.ret.selector, data)) ); assertEq(ret.length, 1); bytes memory actual = abi.decode(ret[0], (bytes)); assertEq(keccak256(actual), keccak256(data)); } - } diff --git a/test/KernelExecutorTest.sol b/test/KernelExecutorTest.sol index 51cbd050..1a47ed95 100644 --- a/test/KernelExecutorTest.sol +++ b/test/KernelExecutorTest.sol @@ -49,7 +49,6 @@ abstract contract KernelExecutorTest is KernelTestBase { assertEq(callee.bar(), 1); } - function test_execute_batch_from_executor() external unitTestExecutor { Call[] memory calls = new Call[](2); calls[0] = Call({to: address(callee), value: 0, data: abi.encodeWithSelector(MockCallee.foo.selector)}); diff --git a/test/halmos/KernelExecutorHalmos.t.sol b/test/halmos/KernelExecutorHalmos.t.sol index 27c76fc6..056447a5 100644 --- a/test/halmos/KernelExecutorHalmos.t.sol +++ b/test/halmos/KernelExecutorHalmos.t.sol @@ -1,4 +1,5 @@ pragma solidity ^0.8.0; + import {Test} from "forge-std/Test.sol"; import {SymTest} from "halmos-cheatcodes/SymTest.sol"; import {MockCallee} from "../mock/MockCallee.sol"; @@ -19,40 +20,41 @@ contract KernelExecutorHalmos is SymTest, Test { kernel.installModule(2, executor, abi.encode(hex"", "")); vm.stopPrank(); } - + function check_execute_from_executor_return0() external { execute_from_executor(0); } - + function check_execute_from_executor_return8() external { execute_from_executor(8); } - + function check_execute_from_executor_return32() external { execute_from_executor(32); } - + function check_execute_from_executor_return64() external { execute_from_executor(64); } - + function check_execute_from_executor_return256() external { execute_from_executor(256); } - + function check_execute_from_executor_return1024() external { execute_from_executor(1024); } - + function check_execute_from_executor_return4096() external { execute_from_executor(4096); } - + function execute_from_executor(uint256 length) internal { - bytes memory data = svm.createBytes(length, 'data'); + bytes memory data = svm.createBytes(length, "data"); vm.startPrank(executor); bytes[] memory ret = kernel.executeFromExecutor( - bytes32(0), abi.encodePacked(address(callee), uint256(0), abi.encodeWithSelector(MockCallee.ret.selector, data)) + bytes32(0), + abi.encodePacked(address(callee), uint256(0), abi.encodeWithSelector(MockCallee.ret.selector, data)) ); assertEq(ret.length, 1); bytes memory actual = abi.decode(ret[0], (bytes)); diff --git a/test/mock/MockCallee.sol b/test/mock/MockCallee.sol index 04d41f44..24f82cb5 100644 --- a/test/mock/MockCallee.sol +++ b/test/mock/MockCallee.sol @@ -21,7 +21,7 @@ contract MockCallee { revert Haha(); } - function ret(bytes memory dat) external pure returns(bytes memory) { + function ret(bytes memory dat) external pure returns (bytes memory) { return dat; } } diff --git a/test/mock/MockExecutor.sol b/test/mock/MockExecutor.sol index cdf2caf2..84cdc152 100644 --- a/test/mock/MockExecutor.sol +++ b/test/mock/MockExecutor.sol @@ -27,7 +27,7 @@ contract MockExecutor is IExecutor { function sudoDoExec(IERC7579Account account, bytes32 mode, bytes calldata executionCalldata) external payable { bytes[] memory results = account.executeFromExecutor(mode, executionCalldata); - for(uint256 i = 0; i Date: Thu, 2 Oct 2025 21:55:31 +0900 Subject: [PATCH 067/121] fix: batchcall return data checks --- src/core/ExecutionManager.sol | 1 + test/KernelExecuteTest.sol | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/src/core/ExecutionManager.sol b/src/core/ExecutionManager.sol index 26b2fef2..11611665 100644 --- a/src/core/ExecutionManager.sol +++ b/src/core/ExecutionManager.sol @@ -69,6 +69,7 @@ abstract contract ExecutionManager { if (!success) { onRevert(); } + results[i] = _getReturn(); } } } diff --git a/test/KernelExecuteTest.sol b/test/KernelExecuteTest.sol index dc9771d5..5e664b55 100644 --- a/test/KernelExecuteTest.sol +++ b/test/KernelExecuteTest.sol @@ -126,4 +126,24 @@ abstract contract KernelExecuteTest is KernelTestBase { bytes memory actual = abi.decode(ret[0], (bytes)); assertEq(keccak256(actual), keccak256(data)); } + + function test_execute_from_executor_return_data_batch() external { + bytes memory data = hex"deadbeef"; + Call[] memory calls = new Call[](5); + for (uint256 i = 0; i < calls.length; i++) { + calls[i] = Call({ + to: address(callee), + value: uint256(0), + data: abi.encodeWithSelector(MockCallee.ret.selector, abi.encodePacked(hex"deadbeef", bytes1(uint8(i)))) + }); + } + vm.startPrank(executor); + bytes[] memory ret = kernel.executeFromExecutor(bytes32(bytes1(0x01)), abi.encode(calls)); + assertEq(ret.length, 5); + for (uint256 i = 0; i < calls.length; i++) { + assertEq( + keccak256(abi.encodePacked(hex"deadbeef", bytes1(uint8(i)))), keccak256(abi.decode(ret[i], (bytes))) + ); + } + } } From c1d6ccbf79fda94bc783d213ed7e8089907b8d2b Mon Sep 17 00:00:00 2001 From: leekt Date: Thu, 25 Sep 2025 16:04:50 +0900 Subject: [PATCH 068/121] fix: do not allow bytes20(0) on setRoot --- snapshots/KernelFactoryTest.json | 2 +- src/core/ValidationManager.sol | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/snapshots/KernelFactoryTest.json b/snapshots/KernelFactoryTest.json index 5f524074..32e4fddb 100644 --- a/snapshots/KernelFactoryTest.json +++ b/snapshots/KernelFactoryTest.json @@ -1,3 +1,3 @@ { - "Mock - deploy()": "159102" + "Mock - deploy()": "159140" } \ No newline at end of file diff --git a/src/core/ValidationManager.sol b/src/core/ValidationManager.sol index 70a528fe..ef4a4999 100644 --- a/src/core/ValidationManager.sol +++ b/src/core/ValidationManager.sol @@ -283,6 +283,7 @@ abstract contract ValidationManager { } function _setRoot(ValidationId vId) internal { + require(ValidationId.unwrap(vId) != bytes20(0), InvalidRootValidation()); ValidationStorage storage $ = _validationStorage(); $.root = vId; } From 7750c812e8aa96254dbd9e952509a017f389e337 Mon Sep 17 00:00:00 2001 From: leekt Date: Mon, 6 Oct 2025 22:34:48 +0900 Subject: [PATCH 069/121] fix: remove validationId check from setRoot --- src/core/ValidationManager.sol | 1 - 1 file changed, 1 deletion(-) diff --git a/src/core/ValidationManager.sol b/src/core/ValidationManager.sol index ef4a4999..70a528fe 100644 --- a/src/core/ValidationManager.sol +++ b/src/core/ValidationManager.sol @@ -283,7 +283,6 @@ abstract contract ValidationManager { } function _setRoot(ValidationId vId) internal { - require(ValidationId.unwrap(vId) != bytes20(0), InvalidRootValidation()); ValidationStorage storage $ = _validationStorage(); $.root = vId; } From 5695f190d42074289a4bb6f236cd6b95bd5ac1ed Mon Sep 17 00:00:00 2001 From: leekt Date: Mon, 6 Oct 2025 22:36:57 +0900 Subject: [PATCH 070/121] fix: setRoot with package reverts if vId == 0 --- src/core/ValidationManager.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/ValidationManager.sol b/src/core/ValidationManager.sol index 70a528fe..5d76878c 100644 --- a/src/core/ValidationManager.sol +++ b/src/core/ValidationManager.sol @@ -279,6 +279,7 @@ abstract contract ValidationManager { } else { revert InvalidRootValidation(); } + require(ValidationId.unwrap(vId) != bytes20(0), InvalidRootValidation()); _setRoot(vId); } From 960943cd2fb8b01fd65eb1200e15549c9b38ca26 Mon Sep 17 00:00:00 2001 From: leekt Date: Mon, 6 Oct 2025 23:08:59 +0900 Subject: [PATCH 071/121] fix: different path for implementation with fallback and --- snapshots/KernelFactoryTest.json | 2 +- src/Kernel7702.sol | 4 ++++ src/KernelImmutableECDSA.sol | 4 ++++ src/core/ValidationManager.sol | 6 +++++- test/Kernel7702.t.sol | 18 ++++++++++++++++++ test/KernelECDSA.t.sol | 17 +++++++++++++++++ test/KernelImmutableECDSA.t.sol | 17 +++++++++++++++++ 7 files changed, 66 insertions(+), 2 deletions(-) diff --git a/snapshots/KernelFactoryTest.json b/snapshots/KernelFactoryTest.json index 32e4fddb..acad2171 100644 --- a/snapshots/KernelFactoryTest.json +++ b/snapshots/KernelFactoryTest.json @@ -1,3 +1,3 @@ { - "Mock - deploy()": "159140" + "Mock - deploy()": "159163" } \ No newline at end of file diff --git a/src/Kernel7702.sol b/src/Kernel7702.sol index e286e45f..5556913d 100644 --- a/src/Kernel7702.sol +++ b/src/Kernel7702.sol @@ -14,4 +14,8 @@ contract Kernel7702 is Kernel { function _statelessInitializeCheck() internal view override returns (bool) { return true; } + + function _fallbackValidatorAvailable() internal pure override returns(bool) { + return true; + } } diff --git a/src/KernelImmutableECDSA.sol b/src/KernelImmutableECDSA.sol index aa397a8c..5f9076b9 100644 --- a/src/KernelImmutableECDSA.sol +++ b/src/KernelImmutableECDSA.sol @@ -24,6 +24,10 @@ contract KernelImmutableECDSA is KernelUUPS { function _statelessInitializeCheck() internal view override returns (bool) { return false; } + + function _fallbackValidatorAvailable() internal pure override returns(bool) { + return true; + } function _initialize(Install[] calldata packages) internal override initializer { _install(packages); diff --git a/src/core/ValidationManager.sol b/src/core/ValidationManager.sol index 5d76878c..bcaf49fc 100644 --- a/src/core/ValidationManager.sol +++ b/src/core/ValidationManager.sol @@ -279,11 +279,15 @@ abstract contract ValidationManager { } else { revert InvalidRootValidation(); } - require(ValidationId.unwrap(vId) != bytes20(0), InvalidRootValidation()); _setRoot(vId); } + function _fallbackValidatorAvailable() internal pure virtual returns(bool) { + return false; + } + function _setRoot(ValidationId vId) internal { + require(ValidationId.unwrap(vId) != bytes20(0) || _fallbackValidatorAvailable(), InvalidRootValidation()); ValidationStorage storage $ = _validationStorage(); $.root = vId; } diff --git a/test/Kernel7702.t.sol b/test/Kernel7702.t.sol index 8273c3f8..ee478182 100644 --- a/test/Kernel7702.t.sol +++ b/test/Kernel7702.t.sol @@ -5,6 +5,8 @@ import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOper import {Lib4337} from "src/lib/Lib4337.sol"; import {Kernel7702} from "src/Kernel7702.sol"; import {Kernel} from "src/Kernel.sol"; +import {Install} from "src/types/Structs.sol"; +import {ValidationId} from "src/types/Types.sol"; contract Kernel7702Test is KernelTest { address owner; @@ -47,4 +49,20 @@ contract Kernel7702Test is KernelTest { (uint8 v, bytes32 r, bytes32 s) = vm.sign(ownerKey, hash); kernel.isValidSignature(hash, abi.encodePacked(r, s, v)); } + + function test_change_root_check_vId_0() external unitTest { + Install[] memory packages = new Install[](2); + packages[0] = Install({moduleType: 1, module: address(newValidator), internalData: hex"", moduleData: hex""}); + packages[1] = Install({ + moduleType: 5, + module: address(policy), + internalData: abi.encodePacked(permissionId), + moduleData: hex"" + }); + kernel.installModule(false, 0, packages, enableSig(0, true, false, packages, _rootSignHash)); + + kernel.setRoot(ValidationId.wrap(bytes20(address(newValidator)))); + + kernel.setRoot(ValidationId.wrap(bytes20(0))); + } } diff --git a/test/KernelECDSA.t.sol b/test/KernelECDSA.t.sol index 04aeb9f3..56d50a9d 100644 --- a/test/KernelECDSA.t.sol +++ b/test/KernelECDSA.t.sol @@ -52,4 +52,21 @@ contract KernelECDSATest is KernelTest { (uint8 v, bytes32 r, bytes32 s) = vm.sign(ownerKey, hash); return abi.encodePacked(r, s, v); } + + function test_change_root_check_vId_0() external unitTest { + Install[] memory packages = new Install[](2); + packages[0] = Install({moduleType: 1, module: address(newValidator), internalData: hex"", moduleData: hex""}); + packages[1] = Install({ + moduleType: 5, + module: address(policy), + internalData: abi.encodePacked(permissionId), + moduleData: hex"" + }); + kernel.installModule(false, 0, packages, enableSig(0, true, false, packages, _rootSignHash)); + + kernel.setRoot(ValidationId.wrap(bytes20(address(newValidator)))); + + vm.expectRevert(); + kernel.setRoot(ValidationId.wrap(bytes20(0))); + } } diff --git a/test/KernelImmutableECDSA.t.sol b/test/KernelImmutableECDSA.t.sol index 246cb0c6..a44fd24e 100644 --- a/test/KernelImmutableECDSA.t.sol +++ b/test/KernelImmutableECDSA.t.sol @@ -3,6 +3,7 @@ pragma solidity ^0.8.0; import {KernelTest} from "./Kernel.t.sol"; import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; import {Install} from "src/types/Structs.sol"; +import {ValidationId} from "src/types/Types.sol"; import {Lib4337} from "src/lib/Lib4337.sol"; import {ECDSAValidator} from "./mock/ECDSAValidator.sol"; @@ -39,4 +40,20 @@ contract KernelImmutableECDSATest is KernelTest { (uint8 v, bytes32 r, bytes32 s) = vm.sign(ownerKey, hash); return abi.encodePacked(r, s, v); } + + function test_change_root_check_vId_0() external unitTest { + Install[] memory packages = new Install[](2); + packages[0] = Install({moduleType: 1, module: address(newValidator), internalData: hex"", moduleData: hex""}); + packages[1] = Install({ + moduleType: 5, + module: address(policy), + internalData: abi.encodePacked(permissionId), + moduleData: hex"" + }); + kernel.installModule(false, 0, packages, enableSig(0, true, false, packages, _rootSignHash)); + + kernel.setRoot(ValidationId.wrap(bytes20(address(newValidator)))); + + kernel.setRoot(ValidationId.wrap(bytes20(0))); + } } From 8b3e9f228ceab00fc3aa73f02e76eee17c91e12f Mon Sep 17 00:00:00 2001 From: leekt Date: Thu, 25 Sep 2025 16:58:55 +0900 Subject: [PATCH 072/121] fix: append msg.sender to fallback call --- snapshots/Kernel7702Test.json | 2 +- snapshots/KernelECDSATest.json | 2 +- snapshots/KernelImmutableECDSATest.json | 2 +- snapshots/KernelTest.json | 2 +- src/Kernel.sol | 2 +- src/core/ExecutionManager.sol | 7 +++---- test/KernelSelectorTest.sol | 5 +++++ test/mock/MockFallback.sol | 3 +++ 8 files changed, 16 insertions(+), 9 deletions(-) diff --git a/snapshots/Kernel7702Test.json b/snapshots/Kernel7702Test.json index 1038772c..ff56df85 100644 --- a/snapshots/Kernel7702Test.json +++ b/snapshots/Kernel7702Test.json @@ -1,3 +1,3 @@ { - "Root - foo()": "168608" + "Root - foo()": "168743" } \ No newline at end of file diff --git a/snapshots/KernelECDSATest.json b/snapshots/KernelECDSATest.json index df696f33..f80f446c 100644 --- a/snapshots/KernelECDSATest.json +++ b/snapshots/KernelECDSATest.json @@ -1,3 +1,3 @@ { - "Root - foo()": "180217" + "Root - foo()": "180352" } \ No newline at end of file diff --git a/snapshots/KernelImmutableECDSATest.json b/snapshots/KernelImmutableECDSATest.json index ea876918..c6aeeebf 100644 --- a/snapshots/KernelImmutableECDSATest.json +++ b/snapshots/KernelImmutableECDSATest.json @@ -1,3 +1,3 @@ { - "Root - foo()": "171565" + "Root - foo()": "171700" } \ No newline at end of file diff --git a/snapshots/KernelTest.json b/snapshots/KernelTest.json index 2f7500b9..d0d35a3f 100644 --- a/snapshots/KernelTest.json +++ b/snapshots/KernelTest.json @@ -1,3 +1,3 @@ { - "Root - foo()": "194083" + "Root - foo()": "194218" } \ No newline at end of file diff --git a/src/Kernel.sol b/src/Kernel.sol index 31106d25..089cc145 100644 --- a/src/Kernel.sol +++ b/src/Kernel.sol @@ -183,7 +183,7 @@ abstract contract Kernel is ModuleManager, ExecutionManager { bool success; if ($.callType == CallType.wrap(bytes1(0x00))) { - success = _call($.target, 0, msg.data); + success = _call($.target, 0, abi.encodePacked(msg.data, msg.sender)); } else if ($.callType == CallType.wrap(bytes1(0xff))) { success = _delegateCall($.target, msg.data); } diff --git a/src/core/ExecutionManager.sol b/src/core/ExecutionManager.sol index ef85c4d4..f8418bff 100644 --- a/src/core/ExecutionManager.sol +++ b/src/core/ExecutionManager.sol @@ -80,12 +80,11 @@ abstract contract ExecutionManager { function _onRevertSilent() internal {} - function _call(address target, uint256 value, bytes calldata callData) internal returns (bool success) { + function _call(address target, uint256 value, bytes memory callData) internal returns (bool success) { /// @solidity memory-safe-assembly assembly { - let ptr := mload(0x40) - calldatacopy(ptr, callData.offset, callData.length) - success := call(gas(), target, value, ptr, callData.length, codesize(), 0x00) + let len := mload(callData) + success := call(gas(), target, value, add(callData, 0x20), len, codesize(), 0x00) } } diff --git a/test/KernelSelectorTest.sol b/test/KernelSelectorTest.sol index f0cbf4c3..a117a268 100644 --- a/test/KernelSelectorTest.sol +++ b/test/KernelSelectorTest.sol @@ -9,6 +9,7 @@ import {InvalidSelector} from "src/types/Error.sol"; abstract contract KernelSelectorTest is KernelTestBase { function test_install_selector_call() external unitTest { + address Caller = makeAddr("Caller"); assertTrue(kernel.supportsModule(3)); kernel.installModule( 3, @@ -17,10 +18,14 @@ abstract contract KernelSelectorTest is KernelTestBase { hex"deadbeef", abi.encodePacked(MockFallback.fallbackFunction.selector, bytes1(0x00), address(1)) ) ); + vm.stopPrank(); + vm.startPrank(Caller); vm.expectEmit(address(mockFallback)); emit MockFallback.Foobar(); uint256 res = MockFallback(address(kernel)).fallbackFunction(10); + address caller = mockFallback.caller(); assertEq(res, 100); + assertEq(caller, Caller); SelectorManager.SelectorConfig memory c = kernel.selectorConfig(MockFallback.fallbackFunction.selector); assertEq(address(c.target), address(mockFallback)); assertEq(address(c.hook), address(1)); diff --git a/test/mock/MockFallback.sol b/test/mock/MockFallback.sol index 90dac8aa..1e59efd7 100644 --- a/test/mock/MockFallback.sol +++ b/test/mock/MockFallback.sol @@ -25,6 +25,8 @@ contract MockFallback is IFallback { Callee public callee; + address public caller; + constructor() { callee = new Callee(); } @@ -50,6 +52,7 @@ contract MockFallback is IFallback { } function fallbackFunction(uint256 v) external returns (uint256) { + caller = address(bytes20(msg.data[msg.data.length - 20:])); require(v < 100, Limit()); emit Foobar(); return v * v; From ec30499181627546046e5e12df7ad48df294a8e3 Mon Sep 17 00:00:00 2001 From: leekt Date: Wed, 24 Sep 2025 23:08:45 +0900 Subject: [PATCH 073/121] fix: map transient storage slot for hooks --- src/Kernel.sol | 6 +++--- src/core/ValidationManager.sol | 13 ++++++++++++- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/Kernel.sol b/src/Kernel.sol index 31106d25..f861ef32 100644 --- a/src/Kernel.sol +++ b/src/Kernel.sol @@ -115,7 +115,7 @@ abstract contract Kernel is ModuleManager, ExecutionManager { && $.allowed[vId][bytes4(userOp.callData[4:])], UnauthorizedCallData() ); - validationHook = IHook($.vInfo[vId].hook); + _setValidationHook(userOpHash, IHook($.vInfo[vId].hook)); } else { require(vType == VALIDATION_TYPE_ROOT || $.allowed[vId][bytes4(userOp.callData)], UnauthorizedCallData()); } @@ -129,7 +129,7 @@ abstract contract Kernel is ModuleManager, ExecutionManager { /// execution function executeUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash) external payable { _onlyEntryPointOrSelf(); - bytes memory context = _preHook(validationHook, userOp.callData[4:]); + bytes memory context = _preHook(_validationHook(userOpHash), userOp.callData[4:]); (bool success, bytes memory ret) = address(this).delegatecall(userOp.callData[4:]); // propagete the revert message if (!success) { @@ -137,7 +137,7 @@ abstract contract Kernel is ModuleManager, ExecutionManager { revert(add(ret, 0x20), mload(ret)) } } - _postHook(validationHook, context); + _postHook(_validationHook(userOpHash), context); } function execute(bytes32 mode, bytes calldata executionData) external payable { diff --git a/src/core/ValidationManager.sol b/src/core/ValidationManager.sol index 70a528fe..66fa0574 100644 --- a/src/core/ValidationManager.sol +++ b/src/core/ValidationManager.sol @@ -34,13 +34,24 @@ function parseNonce(uint256 nonce) pure returns (ValidationMode vMode, Validatio abstract contract ValidationManager { ValidationId transient installingPermission; - IHook transient validationHook; function root() external view returns (ValidationId) { ValidationStorage storage $ = _validationStorage(); return $.root; } + function _validationHook(bytes32 userOpHash) internal view returns (IHook hook) { + assembly { + hook := tload(userOpHash) + } + } + + function _setValidationHook(bytes32 userOpHash, IHook hook) internal { + assembly { + tstore(userOpHash, hook) + } + } + function validationInfo(ValidationId vId) external view returns (ValidationInfo memory) { ValidationStorage storage $ = _validationStorage(); return $.vInfo[vId]; From 3a35cba12fb4c12d08dea2f5617dfc8436846ea5 Mon Sep 17 00:00:00 2001 From: leekt Date: Mon, 6 Oct 2025 23:14:30 +0900 Subject: [PATCH 074/121] fmt --- src/Kernel7702.sol | 2 +- src/KernelImmutableECDSA.sol | 4 ++-- src/core/ValidationManager.sol | 2 +- test/Kernel7702.t.sol | 2 +- test/KernelECDSA.t.sol | 2 +- test/KernelImmutableECDSA.t.sol | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Kernel7702.sol b/src/Kernel7702.sol index 5556913d..89e91ddd 100644 --- a/src/Kernel7702.sol +++ b/src/Kernel7702.sol @@ -15,7 +15,7 @@ contract Kernel7702 is Kernel { return true; } - function _fallbackValidatorAvailable() internal pure override returns(bool) { + function _fallbackValidatorAvailable() internal pure override returns (bool) { return true; } } diff --git a/src/KernelImmutableECDSA.sol b/src/KernelImmutableECDSA.sol index 5f9076b9..fbe70567 100644 --- a/src/KernelImmutableECDSA.sol +++ b/src/KernelImmutableECDSA.sol @@ -24,8 +24,8 @@ contract KernelImmutableECDSA is KernelUUPS { function _statelessInitializeCheck() internal view override returns (bool) { return false; } - - function _fallbackValidatorAvailable() internal pure override returns(bool) { + + function _fallbackValidatorAvailable() internal pure override returns (bool) { return true; } diff --git a/src/core/ValidationManager.sol b/src/core/ValidationManager.sol index bcaf49fc..a126e23f 100644 --- a/src/core/ValidationManager.sol +++ b/src/core/ValidationManager.sol @@ -282,7 +282,7 @@ abstract contract ValidationManager { _setRoot(vId); } - function _fallbackValidatorAvailable() internal pure virtual returns(bool) { + function _fallbackValidatorAvailable() internal pure virtual returns (bool) { return false; } diff --git a/test/Kernel7702.t.sol b/test/Kernel7702.t.sol index ee478182..471a0f6f 100644 --- a/test/Kernel7702.t.sol +++ b/test/Kernel7702.t.sol @@ -49,7 +49,7 @@ contract Kernel7702Test is KernelTest { (uint8 v, bytes32 r, bytes32 s) = vm.sign(ownerKey, hash); kernel.isValidSignature(hash, abi.encodePacked(r, s, v)); } - + function test_change_root_check_vId_0() external unitTest { Install[] memory packages = new Install[](2); packages[0] = Install({moduleType: 1, module: address(newValidator), internalData: hex"", moduleData: hex""}); diff --git a/test/KernelECDSA.t.sol b/test/KernelECDSA.t.sol index 56d50a9d..bfc0f8d5 100644 --- a/test/KernelECDSA.t.sol +++ b/test/KernelECDSA.t.sol @@ -52,7 +52,7 @@ contract KernelECDSATest is KernelTest { (uint8 v, bytes32 r, bytes32 s) = vm.sign(ownerKey, hash); return abi.encodePacked(r, s, v); } - + function test_change_root_check_vId_0() external unitTest { Install[] memory packages = new Install[](2); packages[0] = Install({moduleType: 1, module: address(newValidator), internalData: hex"", moduleData: hex""}); diff --git a/test/KernelImmutableECDSA.t.sol b/test/KernelImmutableECDSA.t.sol index a44fd24e..a6bb2678 100644 --- a/test/KernelImmutableECDSA.t.sol +++ b/test/KernelImmutableECDSA.t.sol @@ -40,7 +40,7 @@ contract KernelImmutableECDSATest is KernelTest { (uint8 v, bytes32 r, bytes32 s) = vm.sign(ownerKey, hash); return abi.encodePacked(r, s, v); } - + function test_change_root_check_vId_0() external unitTest { Install[] memory packages = new Install[](2); packages[0] = Install({moduleType: 1, module: address(newValidator), internalData: hex"", moduleData: hex""}); From 69e12fbdd5da06f3eb6c5e12cca8ac16ec965a40 Mon Sep 17 00:00:00 2001 From: leekt Date: Tue, 14 Oct 2025 10:02:14 +0900 Subject: [PATCH 075/121] remove initializer --- src/KernelImmutableECDSA.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/KernelImmutableECDSA.sol b/src/KernelImmutableECDSA.sol index fbe70567..cc10d1f1 100644 --- a/src/KernelImmutableECDSA.sol +++ b/src/KernelImmutableECDSA.sol @@ -29,7 +29,7 @@ contract KernelImmutableECDSA is KernelUUPS { return true; } - function _initialize(Install[] calldata packages) internal override initializer { + function _initialize(Install[] calldata packages) internal override { _install(packages); } } From 75e788bee74f5622b0b51e54cc4a58a26693ee66 Mon Sep 17 00:00:00 2001 From: leekt Date: Tue, 14 Oct 2025 10:02:34 +0900 Subject: [PATCH 076/121] fix --- snapshots/Kernel7702Test.json | 2 +- snapshots/KernelECDSATest.json | 2 +- snapshots/KernelFactoryTest.json | 2 +- snapshots/KernelImmutableECDSATest.json | 2 +- snapshots/KernelTest.json | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/snapshots/Kernel7702Test.json b/snapshots/Kernel7702Test.json index 71fd26ae..7c1562a1 100644 --- a/snapshots/Kernel7702Test.json +++ b/snapshots/Kernel7702Test.json @@ -1,3 +1,3 @@ { - "Root - foo()": "168876" + "Root - foo()": "169011" } \ No newline at end of file diff --git a/snapshots/KernelECDSATest.json b/snapshots/KernelECDSATest.json index 31f519de..85266ffb 100644 --- a/snapshots/KernelECDSATest.json +++ b/snapshots/KernelECDSATest.json @@ -1,3 +1,3 @@ { - "Root - foo()": "180486" + "Root - foo()": "180621" } \ No newline at end of file diff --git a/snapshots/KernelFactoryTest.json b/snapshots/KernelFactoryTest.json index 68737a6f..06ffb1e7 100644 --- a/snapshots/KernelFactoryTest.json +++ b/snapshots/KernelFactoryTest.json @@ -1,3 +1,3 @@ { - "Mock - deploy()": "181649" + "Mock - deploy()": "181714" } \ No newline at end of file diff --git a/snapshots/KernelImmutableECDSATest.json b/snapshots/KernelImmutableECDSATest.json index f39af0f9..f810e23f 100644 --- a/snapshots/KernelImmutableECDSATest.json +++ b/snapshots/KernelImmutableECDSATest.json @@ -1,3 +1,3 @@ { - "Root - foo()": "171834" + "Root - foo()": "171969" } \ No newline at end of file diff --git a/snapshots/KernelTest.json b/snapshots/KernelTest.json index 7bf5ac5e..17a5b9eb 100644 --- a/snapshots/KernelTest.json +++ b/snapshots/KernelTest.json @@ -1,3 +1,3 @@ { - "Root - foo()": "194352" + "Root - foo()": "194487" } \ No newline at end of file From e850e7aa95f9d82c8a05d888aa6fa966089b6453 Mon Sep 17 00:00:00 2001 From: leekt Date: Thu, 25 Sep 2025 14:59:41 +0900 Subject: [PATCH 077/121] fix: signer cannot be address(0) --- src/KernelFactory.sol | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/KernelFactory.sol b/src/KernelFactory.sol index 532d0b6d..d00c1c1c 100644 --- a/src/KernelFactory.sol +++ b/src/KernelFactory.sol @@ -75,6 +75,7 @@ contract KernelFactory { payable returns (Kernel) { + require(signer != address(0), InvalidSigner()); bytes32 salt = keccak256(abi.encode(initialPackages, nonce)); (, address account) = LibClone.createDeterministicERC1967(address(IMMUTABLE_ECDSA), abi.encodePacked(signer), salt); @@ -90,6 +91,7 @@ contract KernelFactory { uint256 nonce, bytes calldata extraCall ) external payable returns (Kernel) { + require(signer != address(0), InvalidSigner()); bytes32 salt = keccak256(abi.encode(initialPackages, nonce)); (, address account) = LibClone.createDeterministicERC1967(address(IMMUTABLE_ECDSA), abi.encodePacked(signer), salt); From 73a61ed5c58d09cab4ecc5863dcc7f02e9f40aa7 Mon Sep 17 00:00:00 2001 From: leekt Date: Mon, 29 Sep 2025 22:01:57 +0900 Subject: [PATCH 078/121] fix: return false on moduleTypeId 0 --- src/Kernel.sol | 4 ++-- test/Kernel.t.sol | 11 +++++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/Kernel.sol b/src/Kernel.sol index cce0cd68..d89a3da8 100644 --- a/src/Kernel.sol +++ b/src/Kernel.sol @@ -289,8 +289,8 @@ abstract contract Kernel is ModuleManager, ExecutionManager, IERC7579Account { return true; } - function supportsModule(uint256 moduleTypeId) external pure override returns (bool) { - return moduleTypeId < 7; + function supportsModule(uint256 moduleTypeId) external pure returns (bool) { + return moduleTypeId < 7 && moduleTypeId != 0; } function isModuleInstalled(uint256 moduleTypeId, address module, bytes calldata additionalContext) diff --git a/test/Kernel.t.sol b/test/Kernel.t.sol index 82dfc873..68c558a4 100644 --- a/test/Kernel.t.sol +++ b/test/Kernel.t.sol @@ -109,4 +109,15 @@ contract KernelTest is vm.expectRevert(NotImplemented.selector); kernel.uninstallModule(10, address(mockHook), abi.encode(hex"", "")); } + + function test_supports_module() external unitTest { + assertFalse(kernel.supportsModule(0)); + assertTrue(kernel.supportsModule(1)); + assertTrue(kernel.supportsModule(2)); + assertTrue(kernel.supportsModule(3)); + assertTrue(kernel.supportsModule(4)); + assertTrue(kernel.supportsModule(5)); + assertTrue(kernel.supportsModule(6)); + assertFalse(kernel.supportsModule(7)); + } } From 35f65fe41bf7cebbb5b052f00b3af4c2303a0b33 Mon Sep 17 00:00:00 2001 From: leekt Date: Tue, 30 Sep 2025 13:43:34 +0900 Subject: [PATCH 079/121] fix: removed install and execute --- src/Kernel.sol | 1 - src/core/ModuleManager.sol | 79 -------------------------------------- 2 files changed, 80 deletions(-) diff --git a/src/Kernel.sol b/src/Kernel.sol index cce0cd68..fbdd4924 100644 --- a/src/Kernel.sol +++ b/src/Kernel.sol @@ -161,7 +161,6 @@ abstract contract Kernel is ModuleManager, ExecutionManager, IERC7579Account { payable returns (bytes[] memory returnData) { - _verifyExecutionData(mode, executionData); return _executeFromExecutor(mode, executionData); } diff --git a/src/core/ModuleManager.sol b/src/core/ModuleManager.sol index 8a287dc3..9d7ab99d 100644 --- a/src/core/ModuleManager.sol +++ b/src/core/ModuleManager.sol @@ -231,83 +231,4 @@ abstract contract ModuleManager is ValidationManager, ExecutorManager, HookManag ); return _verifySignature(vId, address(this), digest, signature); } - - // NOTE : heavily motivated by solady's erc7821 - function _verifyExecutionData(bytes32 mode, bytes calldata executionData) internal returns (bool success) { - uint256 id = _executionModeId(mode); - if (id < 2) { - return true; - } - bytes calldata opData; - Call[] calldata calls; - assembly { - // Use inline assembly to extract the calls and optional `opData` efficiently. - opData.length := 0 - let o := add(executionData.offset, calldataload(executionData.offset)) - calls.offset := add(o, 0x20) - calls.length := calldataload(o) - // If the offset of `executionData` allows for `opData`, and the mode supports it. - if gt(eq(id, 2), gt(0x40, calldataload(executionData.offset))) { - let q := add(executionData.offset, calldataload(add(0x20, executionData.offset))) - opData.offset := add(q, 0x20) - opData.length := calldataload(q) - } - // Bounds checking for `executionData` is skipped here for efficiency. - // This is safe if it is only used as an argument to `execute` externally. - // If `executionData` used as an argument to other functions externally, - // please perform the bounds checks via `LibERC7579.decodeBatchAndOpData` - /// or `abi.decode` in the other functions for safety. - } - InstallAndExecute calldata exec; - assembly { - exec := opData.offset - } - - success = _verifyInstallAndExecuteSignature(mode, calls, exec); - - _install(exec.packages); - } - - // NOTE : heavily motivated by solady's erc7821 - /// @dev 0: invalid mode, 1: no `opData` support, 2: with `opData` support - function _executionModeId(bytes32 mode) internal view virtual returns (uint256 id) { - // Only supports atomic batched executions. - // For the encoding scheme, see: https://eips.ethereum.org/EIPS/eip-7579 - // Bytes Layout: - // - [0] ( 1 byte ) `0x01` for batch call. - // - [1] ( 1 byte ) `0x00` for revert on any failure. - // - [2..5] ( 4 bytes) Reserved by ERC7579 for future standardization. - // - [6..9] ( 4 bytes) `0x00000000` or `0x78210001` or `0x78210002`. - // - [10..31] (22 bytes) Unused. Free for use. - /// @solidity memory-safe-assembly - assembly { - let m := and(shr(mul(22, 8), mode), 0xffff00000000ffffffff) - id := eq(m, 0x01000000000000000000) // 1. - id := or(shl(1, eq(m, 0x01000000000078210001)), id) // 2. - } - } - - function _verifyInstallAndExecuteSignature(bytes32 mode, Call[] calldata calls, InstallAndExecute calldata opData) - internal - returns (bool) - { - ValidationId vId = _validationStorage().root; - function(bytes32) internal view returns(bytes32) hashTypedData = - opData.replayable ? _hashTypedDataSansChainId : _hashTypedData; - require(_checkNonce(opData.nonce), InvalidNonce()); - bytes32 digest = hashTypedData( - keccak256( - abi.encode( - keccak256( - "ExecuteWithInstall(bytes32 mode, bytes execData,uint256 nonce,Install[] packages)Install(uint256 moduleType,address module,bytes moduleData,bytes internalData)" - ), - mode, - keccak256(abi.encode(calls)), - opData.nonce, - _installHash(opData.packages) - ) - ) - ); - return Lib4337.checkValidation(_verifySignature(vId, address(this), digest, opData.signature)); - } } From 7f553742b67bd80b9a903bd6c7b5c0d0a40945ee Mon Sep 17 00:00:00 2001 From: leekt Date: Tue, 30 Sep 2025 13:49:25 +0900 Subject: [PATCH 080/121] fix: check if executor is installed when executeFromExecutor is called --- src/core/ModuleManager.sol | 3 ++- test/KernelExecutorTest.sol | 50 ++++++++----------------------------- 2 files changed, 12 insertions(+), 41 deletions(-) diff --git a/src/core/ModuleManager.sol b/src/core/ModuleManager.sol index 9d7ab99d..32a56ad5 100644 --- a/src/core/ModuleManager.sol +++ b/src/core/ModuleManager.sol @@ -6,7 +6,7 @@ import {ExecutorManager} from "./ExecutorManager.sol"; import {HookManager} from "./HookManager.sol"; import {SelectorManager} from "./SelectorManager.sol"; import {ERC1271} from "../lib/ERC1271.sol"; -import {InvalidNonce, NotImplemented} from "../types/Error.sol"; +import {InvalidNonce, NotImplemented, Unauthorized} from "../types/Error.sol"; import {ModuleInstalled, ModuleUninstalled} from "../types/Events.sol"; import {Install, Call, InstallAndExecute} from "../types/Structs.sol"; import {ValidationId} from "../types/Types.sol"; @@ -23,6 +23,7 @@ struct ModuleStorage { abstract contract ModuleManager is ValidationManager, ExecutorManager, HookManager, SelectorManager, ERC1271 { modifier executorHook() { IHook hook = _executorConfig(IExecutor(msg.sender)).hook; + require(address(hook) != address(0), Unauthorized()); bytes memory hookData = _preHook(hook, msg.data); _; _postHook(hook, hookData); diff --git a/test/KernelExecutorTest.sol b/test/KernelExecutorTest.sol index 1a47ed95..540e49e1 100644 --- a/test/KernelExecutorTest.sol +++ b/test/KernelExecutorTest.sol @@ -9,6 +9,16 @@ import {MockKernel} from "./mock/MockKernel.sol"; import {KernelTestBase} from "./KernelTestBase.sol"; abstract contract KernelExecutorTest is KernelTestBase { + + function test_execute_from_executor_fail_not_executor() external { + address notExecutor = makeAddr("not executor"); + vm.startPrank(notExecutor); + vm.expectRevert(); + kernel.executeFromExecutor( + bytes32(0), abi.encodePacked(address(callee), uint256(0), abi.encodeWithSelector(MockCallee.foo.selector)) + ); + } + function test_install_executor_oninstall_success() external unitTest { assertTrue(kernel.supportsModule(2)); address newEx = address(new MockExecutor()); @@ -63,46 +73,6 @@ abstract contract KernelExecutorTest is KernelTestBase { assertEq(callee.data(), "lorem ipsum"); } - bytes32 constant MODE_EXECUTE_WITH_OP_DATA = bytes10(0x01000000000078210001); - - function encodeInstallWithExecute(Call[] memory calls, bool replayable, uint256 nonce, Install[] memory packages) - internal - returns (bytes memory sig) - { - InstallAndExecute memory ie = - InstallAndExecute({replayable: replayable, nonce: nonce, packages: packages, signature: hex""}); - bytes32 hash = helper.installAndExecuteDigest(address(kernel), MODE_EXECUTE_WITH_OP_DATA, calls, ie); - - MockKernel mockKernel = new MockKernel(ep); - - if (!is7702) { - vm.store(address(kernel), ERC1967_IMPLEMENTATION_SLOT, bytes32(uint256(uint160(address(mockKernel))))); - assertEq( - MockKernel(payable(address(kernel))).installAndExecuteDigest(MODE_EXECUTE_WITH_OP_DATA, calls, ie), hash - ); - } - sig = abi.encode(false, uint256(0), packages, _rootSignHash(hash, true)); - } - - function test_execute_batch_from_executor_with_install_data() external { - address newExecutor = makeAddr("New Executor"); - Install[] memory packages = new Install[](1); - packages[0] = Install({moduleType: 2, module: newExecutor, internalData: hex"", moduleData: hex""}); - - Call[] memory calls = new Call[](2); - calls[0] = Call({to: address(callee), value: 0, data: abi.encodeWithSelector(MockCallee.foo.selector)}); - calls[1] = Call({to: address(callee), value: 0, data: abi.encodeWithSelector(MockCallee.lorem.selector)}); - assertEq(callee.data(), ""); - vm.startPrank(newExecutor); - bytes memory installData = encodeInstallWithExecute(calls, false, uint256(0), packages); - vm.expectEmit(address(callee)); - emit MockCallee.Lorem(); - kernel.executeFromExecutor(MODE_EXECUTE_WITH_OP_DATA, abi.encode(calls, installData)); - assertEq(callee.bar(), 1); - assertEq(callee.data(), "lorem ipsum"); - vm.stopPrank(); - } - function test_execute_delegatecall_from_executor() external unitTestExecutor { vm.expectEmit(address(kernel)); emit MockCallee.Lorem(); From eff654243aefdc6a20bee811c9f615f806d1aad2 Mon Sep 17 00:00:00 2001 From: leekt Date: Tue, 30 Sep 2025 13:56:08 +0900 Subject: [PATCH 081/121] fmt --- test/KernelExecutorTest.sol | 1 - 1 file changed, 1 deletion(-) diff --git a/test/KernelExecutorTest.sol b/test/KernelExecutorTest.sol index 540e49e1..93ae2f8f 100644 --- a/test/KernelExecutorTest.sol +++ b/test/KernelExecutorTest.sol @@ -9,7 +9,6 @@ import {MockKernel} from "./mock/MockKernel.sol"; import {KernelTestBase} from "./KernelTestBase.sol"; abstract contract KernelExecutorTest is KernelTestBase { - function test_execute_from_executor_fail_not_executor() external { address notExecutor = makeAddr("not executor"); vm.startPrank(notExecutor); From ff20f6c6b78ed4d9eaa88681330476306ce813da Mon Sep 17 00:00:00 2001 From: leekt Date: Tue, 14 Oct 2025 10:15:06 +0900 Subject: [PATCH 082/121] fix: added back the invalidSigner error --- src/KernelFactory.sol | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/KernelFactory.sol b/src/KernelFactory.sol index d00c1c1c..aafcfee9 100644 --- a/src/KernelFactory.sol +++ b/src/KernelFactory.sol @@ -6,6 +6,8 @@ import {KernelImmutableECDSA} from "./KernelImmutableECDSA.sol"; import {LibClone} from "solady/utils/LibClone.sol"; contract KernelFactory { + error InvalidSigner(); + KernelUUPS public immutable UUPS; KernelImmutableECDSA public immutable IMMUTABLE_ECDSA; From a691aad266631e3621c52c8b2837b91821b50f5d Mon Sep 17 00:00:00 2001 From: leekt Date: Wed, 24 Sep 2025 23:10:39 +0900 Subject: [PATCH 083/121] feat: setRoot to allow installing and removing previous root validator --- src/Kernel.sol | 43 ++++++++++++++++++++++++++++++--- src/core/ValidationManager.sol | 14 ++++++++--- src/types/Error.sol | 1 + test/KernelImmutableECDSA.t.sol | 1 + 4 files changed, 53 insertions(+), 6 deletions(-) diff --git a/src/Kernel.sol b/src/Kernel.sol index 3e2fa093..9b1bf95a 100644 --- a/src/Kernel.sol +++ b/src/Kernel.sol @@ -2,8 +2,8 @@ pragma solidity ^0.8.0; import {IEntryPoint} from "account-abstraction/interfaces/IEntryPoint.sol"; import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; -import {IExecutor, IHook} from "./interfaces/IERC7579Modules.sol"; import {IERC7579Account} from "./interfaces/IERC7579Account.sol"; +import {IValidator, IExecutor, IHook, IModule} from "./interfaces/IERC7579Modules.sol"; import {ModuleManager, Install} from "./core/ModuleManager.sol"; import {parseNonce} from "./core/ValidationManager.sol"; import {ExecutionManager} from "./core/ExecutionManager.sol"; @@ -249,9 +249,46 @@ abstract contract Kernel is ModuleManager, ExecutionManager, IERC7579Account { _uninstallModule(moduleType, module, imdf.installData, imdf.internalData); } - function setRoot(ValidationId vId) external payable { + struct PermissionUninstallData { + bytes[] uninstallData; + } + + // we are going to let array of pkgs to be installed and use first one as root + function setRoot(Install[] calldata pkg, bool removeCurrent, bytes calldata uninstallData) external payable { _onlyEntryPointOrSelf(); - _setRoot(vId); + ValidationId currentRoot = _validationStorage().root; + if(removeCurrent) { + ValidationId vId = _validationStorage().root; + ValidationInfo memory vInfo = _validationStorage().vInfo[vId]; + if(vInfo.vType == VALIDATION_TYPE_VALIDATOR) { + (bool success, ) = address(ValidationId.unwrap(vId)).call(abi.encodeWithSelector(IModule.onUninstall.selector, uninstallData)); + _uninstallValidator( + address(ValidationId.unwrap(vId)), + // passing in uninstallData here to use calldata, but it's never used + uninstallData, + success + ); + } else if(vInfo.vType == VALIDATION_TYPE_PERMISSION) { + PermissionUninstallData calldata data; + assembly { + data := uninstallData.offset + } + bytes[] calldata uninstallDataArr = data.uninstallData; + require(uninstallDataArr.length == vInfo.policies.length + 1, InvalidDataLength()); + // uninstall policies first + for(uint256 i = 0; i Date: Wed, 24 Sep 2025 23:11:32 +0900 Subject: [PATCH 084/121] fmt --- src/Kernel.sol | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/Kernel.sol b/src/Kernel.sol index 9b1bf95a..8a2e4f9c 100644 --- a/src/Kernel.sol +++ b/src/Kernel.sol @@ -257,18 +257,20 @@ abstract contract Kernel is ModuleManager, ExecutionManager, IERC7579Account { function setRoot(Install[] calldata pkg, bool removeCurrent, bytes calldata uninstallData) external payable { _onlyEntryPointOrSelf(); ValidationId currentRoot = _validationStorage().root; - if(removeCurrent) { + if (removeCurrent) { ValidationId vId = _validationStorage().root; ValidationInfo memory vInfo = _validationStorage().vInfo[vId]; - if(vInfo.vType == VALIDATION_TYPE_VALIDATOR) { - (bool success, ) = address(ValidationId.unwrap(vId)).call(abi.encodeWithSelector(IModule.onUninstall.selector, uninstallData)); + if (vInfo.vType == VALIDATION_TYPE_VALIDATOR) { + (bool success,) = address(ValidationId.unwrap(vId)).call( + abi.encodeWithSelector(IModule.onUninstall.selector, uninstallData) + ); _uninstallValidator( address(ValidationId.unwrap(vId)), // passing in uninstallData here to use calldata, but it's never used uninstallData, success ); - } else if(vInfo.vType == VALIDATION_TYPE_PERMISSION) { + } else if (vInfo.vType == VALIDATION_TYPE_PERMISSION) { PermissionUninstallData calldata data; assembly { data := uninstallData.offset @@ -276,12 +278,14 @@ abstract contract Kernel is ModuleManager, ExecutionManager, IERC7579Account { bytes[] calldata uninstallDataArr = data.uninstallData; require(uninstallDataArr.length == vInfo.policies.length + 1, InvalidDataLength()); // uninstall policies first - for(uint256 i = 0; i Date: Thu, 25 Sep 2025 14:53:09 +0900 Subject: [PATCH 085/121] merged --- src/Kernel.sol | 6 ++++-- test/KernelTestBase.sol | 1 + test/KernelValidatorTest.sol | 18 ++++++++++++++++-- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/Kernel.sol b/src/Kernel.sol index 8a2e4f9c..f52f5fb3 100644 --- a/src/Kernel.sol +++ b/src/Kernel.sol @@ -25,10 +25,12 @@ import { UnauthorizedCallData, InvalidSelector, InvalidInitialization, - InstallSignatureVerificationFailed + InstallSignatureVerificationFailed, + InvalidDataLength, + InvalidRootValidation } from "./types/Error.sol"; import {Received} from "./types/Events.sol"; -import {VALIDATION_TYPE_ROOT} from "./types/Constants.sol"; +import {VALIDATION_TYPE_ROOT, VALIDATION_TYPE_PERMISSION, VALIDATION_TYPE_VALIDATOR} from "./types/Constants.sol"; import {ValidationStorage, ValidationInfo} from "./types/Structs.sol"; abstract contract Kernel is ModuleManager, ExecutionManager, IERC7579Account { diff --git a/test/KernelTestBase.sol b/test/KernelTestBase.sol index 001aadea..3b157c70 100644 --- a/test/KernelTestBase.sol +++ b/test/KernelTestBase.sol @@ -40,6 +40,7 @@ abstract contract KernelTestBase is Test { KernelHelper helper; bool is7702; + bool isImmutable; modifier unitTest() { vm.startPrank(address(ep)); diff --git a/test/KernelValidatorTest.sol b/test/KernelValidatorTest.sol index 965dcd26..cf5b9ae2 100644 --- a/test/KernelValidatorTest.sol +++ b/test/KernelValidatorTest.sol @@ -72,9 +72,23 @@ abstract contract KernelValidatorTest is KernelTestBase { internalData: abi.encodePacked(permissionId), moduleData: hex"" }); - kernel.installModule(false, 0, packages, enableSig(0, true, false, packages, _rootSignHash)); - kernel.setRoot(ValidationId.wrap(bytes20(address(newValidator)))); + kernel.setRoot(packages, false, hex""); + } + + function test_change_root_remove_previous_validator() external unitTest { + vm.skip(is7702); + vm.skip(isImmutable); + Install[] memory packages = new Install[](2); + packages[0] = Install({moduleType: 1, module: address(newValidator), internalData: hex"", moduleData: hex""}); + packages[1] = Install({ + moduleType: 5, + module: address(policy), + internalData: abi.encodePacked(permissionId), + moduleData: hex"" + }); + + kernel.setRoot(packages, true, hex""); } function test_install_validator() external unitTest { From f646dec8b3dc509e9a0c828b75501955d3299859 Mon Sep 17 00:00:00 2001 From: leekt Date: Tue, 14 Oct 2025 22:37:29 +0900 Subject: [PATCH 086/121] feat: add explicit setRoot(validationId) --- snapshots/Kernel7702Test.json | 2 +- snapshots/KernelECDSATest.json | 2 +- snapshots/KernelFactoryTest.json | 2 +- snapshots/KernelImmutableECDSATest.json | 2 +- snapshots/KernelTest.json | 2 +- src/Kernel.sol | 5 +++++ test/Kernel7702.t.sol | 3 +-- 7 files changed, 11 insertions(+), 7 deletions(-) diff --git a/snapshots/Kernel7702Test.json b/snapshots/Kernel7702Test.json index 7c1562a1..69e1364b 100644 --- a/snapshots/Kernel7702Test.json +++ b/snapshots/Kernel7702Test.json @@ -1,3 +1,3 @@ { - "Root - foo()": "169011" + "Root - foo()": "168967" } \ No newline at end of file diff --git a/snapshots/KernelECDSATest.json b/snapshots/KernelECDSATest.json index 85266ffb..f301d3d8 100644 --- a/snapshots/KernelECDSATest.json +++ b/snapshots/KernelECDSATest.json @@ -1,3 +1,3 @@ { - "Root - foo()": "180621" + "Root - foo()": "180588" } \ No newline at end of file diff --git a/snapshots/KernelFactoryTest.json b/snapshots/KernelFactoryTest.json index 06ffb1e7..72518a4c 100644 --- a/snapshots/KernelFactoryTest.json +++ b/snapshots/KernelFactoryTest.json @@ -1,3 +1,3 @@ { - "Mock - deploy()": "181714" + "Mock - deploy()": "181681" } \ No newline at end of file diff --git a/snapshots/KernelImmutableECDSATest.json b/snapshots/KernelImmutableECDSATest.json index f810e23f..fca9a911 100644 --- a/snapshots/KernelImmutableECDSATest.json +++ b/snapshots/KernelImmutableECDSATest.json @@ -1,3 +1,3 @@ { - "Root - foo()": "171969" + "Root - foo()": "171947" } \ No newline at end of file diff --git a/snapshots/KernelTest.json b/snapshots/KernelTest.json index 17a5b9eb..0acf41b8 100644 --- a/snapshots/KernelTest.json +++ b/snapshots/KernelTest.json @@ -1,3 +1,3 @@ { - "Root - foo()": "194487" + "Root - foo()": "194454" } \ No newline at end of file diff --git a/src/Kernel.sol b/src/Kernel.sol index f52f5fb3..41a59938 100644 --- a/src/Kernel.sol +++ b/src/Kernel.sol @@ -297,6 +297,11 @@ abstract contract Kernel is ModuleManager, ExecutionManager, IERC7579Account { _setRoot(pkg[0]); } + function setRoot(ValidationId vId) external payable { + _onlyEntryPointOrSelf(); + _setRoot(vId); + } + // NOTE : this ONLY allows root signature, for now function installModule(bool replayable, uint256 nonce, Install[] calldata packages, bytes calldata signature) external diff --git a/test/Kernel7702.t.sol b/test/Kernel7702.t.sol index 37538fd9..b892df3e 100644 --- a/test/Kernel7702.t.sol +++ b/test/Kernel7702.t.sol @@ -59,9 +59,8 @@ contract Kernel7702Test is KernelTest { internalData: abi.encodePacked(permissionId), moduleData: hex"" }); - kernel.installModule(false, 0, packages, enableSig(0, true, false, packages, _rootSignHash)); - kernel.setRoot(ValidationId.wrap(bytes20(address(newValidator)))); + kernel.setRoot(packages, false, hex""); kernel.setRoot(ValidationId.wrap(bytes20(0))); } From b6e1ee474f825427fa8adda0649bb16d8dc8a3ee Mon Sep 17 00:00:00 2001 From: leekt Date: Wed, 15 Oct 2025 00:58:17 +0900 Subject: [PATCH 087/121] bytes21 attempt1 --- foundry.toml | 1 + snapshots/Kernel7702Test.json | 2 +- snapshots/KernelECDSATest.json | 2 +- snapshots/KernelFactoryTest.json | 2 +- snapshots/KernelImmutableECDSATest.json | 2 +- snapshots/KernelTest.json | 2 +- src/Kernel.sol | 16 +++++---- src/core/ModuleManager.sol | 26 ++++++++++---- src/core/ValidationManager.sol | 44 ++++++++++++----------- src/lib/Utils.sol | 37 ++++++++++++++++++++ src/types/Types.sol | 4 ++- test/Kernel.t.sol | 3 +- test/KernelECDSA.t.sol | 2 +- test/KernelERC1271Test.sol | 26 ++++++++------ test/KernelFactory.t.sol | 7 ++-- test/KernelTestBase.sol | 12 +++---- test/KernelUserOpTest.sol | 11 +++--- test/KernelValidatorTest.sol | 46 ++++++++++++++++--------- 18 files changed, 162 insertions(+), 83 deletions(-) diff --git a/foundry.toml b/foundry.toml index 3a5ba691..57d5992d 100644 --- a/foundry.toml +++ b/foundry.toml @@ -6,6 +6,7 @@ via_ir = false # make this true optimizer = true run = 200 evm_version = 'prague' +solc_version = '0.8.30' extra_output = ["storageLayout"] # See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options diff --git a/snapshots/Kernel7702Test.json b/snapshots/Kernel7702Test.json index 69e1364b..8923d0d0 100644 --- a/snapshots/Kernel7702Test.json +++ b/snapshots/Kernel7702Test.json @@ -1,3 +1,3 @@ { - "Root - foo()": "168967" + "Root - foo()": "168958" } \ No newline at end of file diff --git a/snapshots/KernelECDSATest.json b/snapshots/KernelECDSATest.json index f301d3d8..5cbad5ba 100644 --- a/snapshots/KernelECDSATest.json +++ b/snapshots/KernelECDSATest.json @@ -1,3 +1,3 @@ { - "Root - foo()": "180588" + "Root - foo()": "180594" } \ No newline at end of file diff --git a/snapshots/KernelFactoryTest.json b/snapshots/KernelFactoryTest.json index 72518a4c..ee3374f7 100644 --- a/snapshots/KernelFactoryTest.json +++ b/snapshots/KernelFactoryTest.json @@ -1,3 +1,3 @@ { - "Mock - deploy()": "181681" + "Mock - deploy()": "181760" } \ No newline at end of file diff --git a/snapshots/KernelImmutableECDSATest.json b/snapshots/KernelImmutableECDSATest.json index fca9a911..16edffc7 100644 --- a/snapshots/KernelImmutableECDSATest.json +++ b/snapshots/KernelImmutableECDSATest.json @@ -1,3 +1,3 @@ { - "Root - foo()": "171947" + "Root - foo()": "171938" } \ No newline at end of file diff --git a/snapshots/KernelTest.json b/snapshots/KernelTest.json index 0acf41b8..21e7caa6 100644 --- a/snapshots/KernelTest.json +++ b/snapshots/KernelTest.json @@ -1,3 +1,3 @@ { - "Root - foo()": "194454" + "Root - foo()": "194460" } \ No newline at end of file diff --git a/src/Kernel.sol b/src/Kernel.sol index 41a59938..9815aec2 100644 --- a/src/Kernel.sol +++ b/src/Kernel.sol @@ -9,10 +9,13 @@ import {parseNonce} from "./core/ValidationManager.sol"; import {ExecutionManager} from "./core/ExecutionManager.sol"; import {Lib4337} from "./lib/Lib4337.sol"; import {ERC1271} from "./lib/ERC1271.sol"; +import {getValidator, getPermissionId, validatorToIdentifier, permissionToIdentifier} from "./lib/Utils.sol"; + import {LibERC7579} from "solady/accounts/LibERC7579.sol"; import { CallType, ValidationId, + PermissionId, ValidationMode, ValidationType, isEnable, @@ -263,11 +266,10 @@ abstract contract Kernel is ModuleManager, ExecutionManager, IERC7579Account { ValidationId vId = _validationStorage().root; ValidationInfo memory vInfo = _validationStorage().vInfo[vId]; if (vInfo.vType == VALIDATION_TYPE_VALIDATOR) { - (bool success,) = address(ValidationId.unwrap(vId)).call( - abi.encodeWithSelector(IModule.onUninstall.selector, uninstallData) - ); + (bool success,) = + address(getValidator(vId)).call(abi.encodeWithSelector(IModule.onUninstall.selector, uninstallData)); _uninstallValidator( - address(ValidationId.unwrap(vId)), + address(getValidator(vId)), // passing in uninstallData here to use calldata, but it's never used uninstallData, success @@ -347,7 +349,7 @@ abstract contract Kernel is ModuleManager, ExecutionManager, IERC7579Account { returns (bool) { if (moduleTypeId == 1) { - ValidationId vId = ValidationId.wrap(bytes20(module)); + ValidationId vId = validatorToIdentifier(IValidator(module)); return !(_validationStorage().vInfo[vId].vType == VALIDATION_TYPE_ROOT); } else if (moduleTypeId == 2) { return address(_executorConfig(IExecutor(module)).hook) != address(0); @@ -357,7 +359,7 @@ abstract contract Kernel is ModuleManager, ExecutionManager, IERC7579Account { } else if (moduleTypeId == 4) { return _hookStorage().enabled[module]; } else if (moduleTypeId == 5) { - ValidationId vId = ValidationId.wrap(bytes20(additionalContext)); + ValidationId vId = permissionToIdentifier(PermissionId.wrap(bytes4(additionalContext))); ValidationInfo storage $ = _validationStorage().vInfo[vId]; for (uint256 i = 0; i < $.policies.length; i++) { if ($.policies[i] == module) { @@ -366,7 +368,7 @@ abstract contract Kernel is ModuleManager, ExecutionManager, IERC7579Account { } return false; } else if (moduleTypeId == 6) { - ValidationId vId = ValidationId.wrap(bytes20(additionalContext)); + ValidationId vId = permissionToIdentifier(PermissionId.wrap(bytes4(additionalContext))); ValidationInfo storage $ = _validationStorage().vInfo[vId]; return $.signer == module; } else { diff --git a/src/core/ModuleManager.sol b/src/core/ModuleManager.sol index 32a56ad5..a9dade48 100644 --- a/src/core/ModuleManager.sol +++ b/src/core/ModuleManager.sol @@ -1,6 +1,6 @@ pragma solidity ^0.8.0; -import {IHook, IExecutor, IModule} from "../interfaces/IERC7579Modules.sol"; +import {IHook, IExecutor, IModule, IValidator} from "../interfaces/IERC7579Modules.sol"; import {ValidationManager} from "./ValidationManager.sol"; import {ExecutorManager} from "./ExecutorManager.sol"; import {HookManager} from "./HookManager.sol"; @@ -9,10 +9,16 @@ import {ERC1271} from "../lib/ERC1271.sol"; import {InvalidNonce, NotImplemented, Unauthorized} from "../types/Error.sol"; import {ModuleInstalled, ModuleUninstalled} from "../types/Events.sol"; import {Install, Call, InstallAndExecute} from "../types/Structs.sol"; -import {ValidationId} from "../types/Types.sol"; +import {ValidationId, ValidationType, PermissionId} from "../types/Types.sol"; import {calldataKeccak} from "../lib/Utils.sol"; import {Lib4337} from "../lib/Lib4337.sol"; -import {MODULE_MANAGER_STORAGE_SLOT} from "../types/Constants.sol"; +import {getValidator, getPermissionId, validatorToIdentifier, permissionToIdentifier} from "../lib/Utils.sol"; +import { + MODULE_MANAGER_STORAGE_SLOT, + VALIDATION_TYPE_ROOT, + VALIDATION_TYPE_VALIDATOR, + VALIDATION_TYPE_PERMISSION +} from "../types/Constants.sol"; struct ModuleStorage { address registry; // Note : not used on vanila kernel but saving the storage slot for future usage @@ -74,11 +80,19 @@ abstract contract ModuleManager is ValidationManager, ExecutorManager, HookManag override returns (bool) { - ValidationId vId = ValidationId.wrap(bytes20(signature[0:20])); - if (vId == ValidationId.wrap(bytes20(0))) { + ValidationType vType = ValidationType.wrap(bytes1(signature[0])); + ValidationId vId; + if (vType == VALIDATION_TYPE_ROOT) { vId = _validationStorage().root; + signature = signature[1:]; + } else if (vType == VALIDATION_TYPE_VALIDATOR) { + vId = validatorToIdentifier(IValidator(address(bytes20(signature[1:21])))); + signature = signature[21:]; + } else if (vType == VALIDATION_TYPE_PERMISSION) { + vId = permissionToIdentifier(PermissionId.wrap(bytes4(signature[1:5]))); + signature = signature[5:]; } - uint256 validationData = _verifySignature(vId, msg.sender, hash, signature[20:]); + uint256 validationData = _verifySignature(vId, msg.sender, hash, signature); return Lib4337.checkValidation(validationData); } diff --git a/src/core/ValidationManager.sol b/src/core/ValidationManager.sol index ef984b3b..b4fc14cf 100644 --- a/src/core/ValidationManager.sol +++ b/src/core/ValidationManager.sol @@ -12,7 +12,7 @@ import { InvalidPermissionId, InvalidValidator } from "../types/Error.sol"; -import {ValidationId, ValidationType, ValidationMode} from "../types/Types.sol"; +import {ValidationId, PermissionId, ValidationType, ValidationMode} from "../types/Types.sol"; import { VALIDATION_MANAGER_STORAGE_SLOT, VALIDATION_TYPE_ROOT, @@ -22,6 +22,8 @@ import { } from "../types/Constants.sol"; import {ValidationStorage, ValidationInfo, Install} from "../types/Structs.sol"; import {Lib4337} from "../lib/Lib4337.sol"; +import {getValidator, getPermissionId, validatorToIdentifier, permissionToIdentifier} from "../lib/Utils.sol"; +import {console} from "forge-std/console.sol"; function parseNonce(uint256 nonce) pure returns (ValidationMode vMode, ValidationType vType, ValidationId vId) { // 2bytes mode (1byte currentMode, 1byte type) @@ -29,7 +31,7 @@ function parseNonce(uint256 nonce) pure returns (ValidationMode vMode, Validatio // 1byte mode | 1byte type | 20bytes vId | 2byte nonceKey | 8byte nonce == 32bytes vMode = ValidationMode.wrap(bytes1(bytes32(nonce))); vType = ValidationType.wrap(bytes1(bytes32(nonce << 8))); - vId = ValidationId.wrap(bytes20(bytes32(nonce << 16))); + vId = ValidationId.wrap(bytes21(bytes32(nonce << 8))); } abstract contract ValidationManager { @@ -86,7 +88,7 @@ abstract contract ValidationManager { function _installValidator(address _validator, bytes calldata _internalData, bool _installSuccess) internal { require(_installSuccess, ModuleInstallFailed()); ValidationStorage storage $ = _validationStorage(); - ValidationId vId = ValidationId.wrap(bytes20(_validator)); + ValidationId vId = validatorToIdentifier(IValidator(_validator)); require($.vInfo[vId].vType == VALIDATION_TYPE_ROOT, OccupiedValidationId()); $.vInfo[vId].vType = VALIDATION_TYPE_VALIDATOR; _initializeValidation(vId, _internalData); @@ -100,7 +102,7 @@ abstract contract ValidationManager { function _installSigner(address _signer, bytes calldata _internalData, bool _installSuccess) internal { ValidationInfo storage $ = _checkPermissionInstall(_internalData, _installSuccess); $.signer = _signer; - installingPermission = ValidationId.wrap(bytes20(0)); + installingPermission = ValidationId.wrap(bytes21(0)); } function _checkPermissionInstall(bytes calldata _internalData, bool _installSuccess) @@ -108,14 +110,14 @@ abstract contract ValidationManager { returns (ValidationInfo storage $) { require(_installSuccess, ModuleInstallFailed()); - ValidationId vId = ValidationId.wrap(bytes20(_internalData[0:20])); + ValidationId vId = permissionToIdentifier(PermissionId.wrap(bytes4(_internalData[0:4]))); $ = _validationStorage().vInfo[vId]; - if (installingPermission == ValidationId.wrap(bytes20(0))) { - require(vId != ValidationId.wrap(bytes20(0)), "invalid validationId"); + if (installingPermission == ValidationId.wrap(bytes21(0))) { + require(vId != ValidationId.wrap(bytes21(0)), "invalid validationId"); require($.vType == ValidationType.wrap(0x00), "already taken"); installingPermission = vId; $.vType = VALIDATION_TYPE_PERMISSION; - _initializeValidation(vId, _internalData[20:]); + _initializeValidation(vId, _internalData[4:]); } else { require(installingPermission == vId, "permissionId should be consistent"); } @@ -123,12 +125,12 @@ abstract contract ValidationManager { function _uninstallValidator(address _validator, bytes calldata _internalData, bool _uninstallSuccess) internal { ValidationStorage storage $ = _validationStorage(); - ValidationId vId = ValidationId.wrap(bytes20(_validator)); + ValidationId vId = validatorToIdentifier(IValidator(_validator)); $.vInfo[vId].vType = VALIDATION_TYPE_ROOT; } function _uninstallPolicy(address _policy, bytes calldata _internalData, bool _uninstallSuccess) internal { - ValidationId vId = ValidationId.wrap(bytes20(_internalData[0:20])); + ValidationId vId = permissionToIdentifier(PermissionId.wrap(bytes4(_internalData[0:4]))); _uninstallPolicyWithVid(_policy, vId); } @@ -145,7 +147,7 @@ abstract contract ValidationManager { } function _uninstallSigner(address _signer, bytes calldata _internalData, bool _uninstallSuccess) internal { - ValidationId vId = ValidationId.wrap(bytes20(_internalData[0:20])); + ValidationId vId = permissionToIdentifier(PermissionId.wrap(bytes4(_internalData[0:4]))); _uninstallSignerWithVid(_signer, vId); } @@ -168,7 +170,7 @@ abstract contract ValidationManager { ValidationStorage storage $ = _validationStorage(); if (vType == VALIDATION_TYPE_ROOT || $.vInfo[vId].vType == VALIDATION_TYPE_ROOT) { v = $.root; - if (ValidationId.unwrap(v) == bytes20(0)) { + if (ValidationId.unwrap(v) == bytes21(0)) { return (v, _validateUserOpFallback); } vType = $.vInfo[v].vType; @@ -189,12 +191,12 @@ abstract contract ValidationManager { view returns (uint256 validationData) { - if (ValidationId.unwrap(vId) == bytes20(0)) { + if (ValidationId.unwrap(vId) == bytes21(0)) { return _verifyFallbackSignature(_hash, _signature) ? 0 : 1; } ValidationInfo storage vInfo = _validationStorage().vInfo[vId]; if (vInfo.vType == VALIDATION_TYPE_VALIDATOR) { - IValidator validator = IValidator(address(ValidationId.unwrap(vId))); + IValidator validator = getValidator(vId); validationData = validator.isValidSignatureWithSender(requester, _hash, _signature) == ERC1271_MAGICVALUE ? 0 : 1; } else if (vInfo.vType == VALIDATION_TYPE_PERMISSION) { @@ -216,7 +218,7 @@ abstract contract ValidationManager { assembly { permissionSig := _signature.offset } - bytes32 paddedVId = bytes32(ValidationId.unwrap(vId)); + bytes32 paddedVId = bytes32(PermissionId.unwrap(getPermissionId(vId))); for (uint256 i = 0; i < vInfo.policies.length; i++) { IPolicy policy = IPolicy(vInfo.policies[i]); validationData = Lib4337.intersectValidationData( @@ -249,9 +251,9 @@ abstract contract ValidationManager { bytes calldata userOpSignature ) internal returns (uint256 validationData) { // NOTE: removed permission for now, adding back after testing is done - address validator = address(ValidationId.unwrap(vId)); + IValidator validator = getValidator(vId); op.signature = userOpSignature; - return IValidator(validator).validateUserOp(op, opHash); + return validator.validateUserOp(op, opHash); } struct PermissionSignature { @@ -270,7 +272,7 @@ abstract contract ValidationManager { assembly { permissionSig := userOpSignature.offset } - bytes32 paddedVId = bytes32(ValidationId.unwrap(vId)); + bytes32 paddedVId = bytes32(PermissionId.unwrap(getPermissionId(vId))); for (uint256 i = 0; i < vInfo.policies.length; i++) { IPolicy policy = IPolicy(vInfo.policies[i]); op.signature = permissionSig.signatures[i]; @@ -292,9 +294,9 @@ abstract contract ValidationManager { function _setRoot(Install calldata pkg) internal { ValidationId vId; if (pkg.moduleType == 1) { - vId = ValidationId.wrap(bytes20(pkg.module)); + vId = validatorToIdentifier(IValidator(address(bytes20(pkg.module)))); } else if (pkg.moduleType == 5 || pkg.moduleType == 6) { - vId = ValidationId.wrap(bytes20(pkg.internalData[0:20])); + vId = permissionToIdentifier(PermissionId.wrap(bytes4(pkg.internalData[0:4]))); } else { revert InvalidRootValidation(); } @@ -306,7 +308,7 @@ abstract contract ValidationManager { } function _setRoot(ValidationId vId) internal { - require(ValidationId.unwrap(vId) != bytes20(0) || _fallbackValidatorAvailable(), InvalidRootValidation()); + require(ValidationId.unwrap(vId) != bytes21(0) || _fallbackValidatorAvailable(), InvalidRootValidation()); ValidationStorage storage $ = _validationStorage(); $.root = vId; } diff --git a/src/lib/Utils.sol b/src/lib/Utils.sol index d933bdc3..f83e5ea0 100644 --- a/src/lib/Utils.sol +++ b/src/lib/Utils.sol @@ -1,5 +1,8 @@ pragma solidity ^0.8.0; +import {IValidator} from "../interfaces/IERC7579Modules.sol"; +import {ValidationId, ValidationType, PermissionId} from "../types/Types.sol"; + function calldataKeccak(bytes calldata data) pure returns (bytes32 ret) { assembly ("memory-safe") { let mem := mload(0x40) @@ -8,3 +11,37 @@ function calldataKeccak(bytes calldata data) pure returns (bytes32 ret) { ret := keccak256(mem, len) } } + +function getType(ValidationId validator) pure returns (ValidationType vType) { + assembly { + vType := validator + } +} + +function getValidator(ValidationId validator) pure returns (IValidator v) { + assembly { + v := shr(88, validator) + } +} + +function getPermissionId(ValidationId validator) pure returns (PermissionId id) { + assembly { + id := shl(8, validator) + } +} + +function validatorToIdentifier(IValidator validator) pure returns (ValidationId vId) { + assembly { + vId := 0x0100000000000000000000000000000000000000000000000000000000000000 + vId := or(vId, shl(88, validator)) + vId := and(0xffffffffffffffffffffffffffffffffffffffffff0000000000000000000000, vId) + } +} + +function permissionToIdentifier(PermissionId permissionId) pure returns (ValidationId vId) { + assembly { + vId := 0x0200000000000000000000000000000000000000000000000000000000000000 + vId := or(vId, shr(8, permissionId)) + vId := and(0xffffffffff000000000000000000000000000000000000000000000000000000, vId) + } +} diff --git a/src/types/Types.sol b/src/types/Types.sol index 1fb15f29..44d29de6 100644 --- a/src/types/Types.sol +++ b/src/types/Types.sol @@ -20,7 +20,9 @@ function isEnableReplayable(ValidationMode vMode) pure returns (bool replayable) return ValidationMode.unwrap(vMode) & bytes1(0x04) != 0; } -type ValidationId is bytes20; +type ValidationId is bytes21; + +type PermissionId is bytes4; type ValidationType is bytes1; diff --git a/test/Kernel.t.sol b/test/Kernel.t.sol index 9b98823b..f0dfa090 100644 --- a/test/Kernel.t.sol +++ b/test/Kernel.t.sol @@ -23,6 +23,7 @@ import {KernelValidatorTest} from "./KernelValidatorTest.sol"; import {KernelExecuteTest} from "./KernelExecuteTest.sol"; import {KernelSelectorTest} from "./KernelSelectorTest.sol"; import {KernelHookTest} from "./KernelHookTest.sol"; +import {PermissionId} from "src/types/Types.sol"; contract KernelTest is KernelUserOpTest, @@ -49,7 +50,7 @@ contract KernelTest is beneficiary = payable(makeAddr("Beneficiary")); policy = new MockPolicy(); signer = new MockSigner(); - permissionId = bytes20(keccak256(abi.encodePacked("Hello world"))); + permissionId = PermissionId.wrap(bytes4(keccak256(abi.encodePacked("Hello world")))); _initialize(); } diff --git a/test/KernelECDSA.t.sol b/test/KernelECDSA.t.sol index bfc0f8d5..91ec546d 100644 --- a/test/KernelECDSA.t.sol +++ b/test/KernelECDSA.t.sol @@ -31,7 +31,7 @@ contract KernelECDSATest is KernelTest { ValidationId vId = kernel.root(); - assertEq(ValidationId.unwrap(vId), bytes20(address(rootValidator))); + assertEq(ValidationId.unwrap(vId), bytes21(abi.encodePacked(bytes1(0x01), address(rootValidator)))); ValidationInfo memory info = kernel.validationInfo(vId); } diff --git a/test/KernelERC1271Test.sol b/test/KernelERC1271Test.sol index e32316bb..14c9e2a0 100644 --- a/test/KernelERC1271Test.sol +++ b/test/KernelERC1271Test.sol @@ -21,7 +21,7 @@ abstract contract KernelERC1271Test is KernelTestBase { bytes32 messageHash = keccak256("Hello world"); (bytes32 contentsHash, bytes memory sig) = _erc1271Signature(messageHash, "C(bytes32 stuff)", "", _rootSignHash, false, true); - bytes4 ret = kernel.isValidSignature(_toContentsHash(contentsHash), abi.encodePacked(bytes20(0), sig)); + bytes4 ret = kernel.isValidSignature(_toContentsHash(contentsHash), abi.encodePacked(bytes1(0), sig)); assertEq(ret, ERC1271_MAGICVALUE); } @@ -38,7 +38,7 @@ abstract contract KernelERC1271Test is KernelTestBase { bytes32 messageHash = keccak256("Hello world"); (bytes32 contentsHash, bytes memory sig) = _erc1271Signature(messageHash, "C(bytes32 stuff)", "", _rootSignHash, false, false); - bytes4 ret = kernel.isValidSignature(_toContentsHash(contentsHash), abi.encodePacked(bytes20(0), sig)); + bytes4 ret = kernel.isValidSignature(_toContentsHash(contentsHash), abi.encodePacked(bytes1(0), sig)); assertEq(ret, ERC1271_INVALID); } @@ -46,7 +46,7 @@ abstract contract KernelERC1271Test is KernelTestBase { bytes32 messageHash = keccak256("Hello world"); bytes32 personalHash = _toErc1271HashPersonalSign(messageHash); bytes memory sig = _rootSignHash(personalHash, true); - bytes4 ret = kernel.isValidSignature(messageHash, abi.encodePacked(bytes20(0), sig)); + bytes4 ret = kernel.isValidSignature(messageHash, abi.encodePacked(bytes1(0), sig)); assertEq(ret, ERC1271_MAGICVALUE); } @@ -54,7 +54,7 @@ abstract contract KernelERC1271Test is KernelTestBase { bytes32 messageHash = keccak256("Hello world"); bytes32 personalHash = _toErc1271HashPersonalSign(messageHash); bytes memory sig = _rootSignHash(personalHash, false); - bytes4 ret = kernel.isValidSignature(messageHash, abi.encodePacked(bytes20(0), sig)); + bytes4 ret = kernel.isValidSignature(messageHash, abi.encodePacked(bytes1(0), sig)); assertEq(ret, ERC1271_INVALID); } @@ -64,7 +64,7 @@ abstract contract KernelERC1271Test is KernelTestBase { _erc1271Signature(messageHash, "C(bytes32 stuff)", "", _validatorSignHash, false, true); kernel.installModule(1, address(newValidator), abi.encode(hex"", hex"")); bytes4 ret = kernel.isValidSignature( - _toContentsHash(contentsHash), abi.encodePacked(bytes20(address(newValidator)), sig) + _toContentsHash(contentsHash), abi.encodePacked(bytes1(0x01), bytes20(address(newValidator)), sig) ); assertEq(ret, ERC1271_MAGICVALUE); } @@ -75,7 +75,7 @@ abstract contract KernelERC1271Test is KernelTestBase { _erc1271Signature(messageHash, "C(bytes32 stuff)", "", _validatorSignHash, false, false); kernel.installModule(1, address(newValidator), abi.encode(hex"", hex"")); bytes4 ret = kernel.isValidSignature( - _toContentsHash(contentsHash), abi.encodePacked(bytes20(address(newValidator)), sig) + _toContentsHash(contentsHash), abi.encodePacked(bytes1(0x01), bytes20(address(newValidator)), sig) ); assertEq(ret, ERC1271_INVALID); } @@ -85,7 +85,8 @@ abstract contract KernelERC1271Test is KernelTestBase { bytes32 personalHash = _toErc1271HashPersonalSign(messageHash); bytes memory sig = _validatorSignHash(personalHash, true); kernel.installModule(1, address(newValidator), abi.encode(hex"", hex"")); - bytes4 ret = kernel.isValidSignature(messageHash, abi.encodePacked(bytes20(address(newValidator)), sig)); + bytes4 ret = + kernel.isValidSignature(messageHash, abi.encodePacked(bytes1(0x01), bytes20(address(newValidator)), sig)); assertEq(ret, ERC1271_MAGICVALUE); } @@ -94,7 +95,8 @@ abstract contract KernelERC1271Test is KernelTestBase { bytes32 personalHash = _toErc1271HashPersonalSign(messageHash); bytes memory sig = _validatorSignHash(personalHash, false); kernel.installModule(1, address(newValidator), abi.encode(hex"", hex"")); - bytes4 ret = kernel.isValidSignature(messageHash, abi.encodePacked(bytes20(address(newValidator)), sig)); + bytes4 ret = + kernel.isValidSignature(messageHash, abi.encodePacked(bytes1(0x01), bytes20(address(newValidator)), sig)); assertEq(ret, ERC1271_INVALID); } @@ -104,7 +106,8 @@ abstract contract KernelERC1271Test is KernelTestBase { _erc1271Signature(messageHash, "C(bytes32 stuff)", "", _permissionSignHash, false, true); kernel.installModule(5, address(policy), abi.encode(hex"deadbeef", abi.encodePacked(permissionId))); kernel.installModule(6, address(signer), abi.encode(hex"deadbeef", abi.encodePacked(permissionId))); - bytes4 ret = kernel.isValidSignature(_toContentsHash(contentsHash), abi.encodePacked(permissionId, sig)); + bytes4 ret = + kernel.isValidSignature(_toContentsHash(contentsHash), abi.encodePacked(bytes1(0x02), permissionId, sig)); assertEq(ret, ERC1271_MAGICVALUE); } @@ -114,7 +117,8 @@ abstract contract KernelERC1271Test is KernelTestBase { _erc1271Signature(messageHash, "C(bytes32 stuff)", "", _permissionSignHash, false, false); kernel.installModule(5, address(policy), abi.encode(hex"deadbeef", abi.encodePacked(permissionId))); kernel.installModule(6, address(signer), abi.encode(hex"deadbeef", abi.encodePacked(permissionId))); - bytes4 ret = kernel.isValidSignature(_toContentsHash(contentsHash), abi.encodePacked(permissionId, sig)); + bytes4 ret = + kernel.isValidSignature(_toContentsHash(contentsHash), abi.encodePacked(bytes1(0x02), permissionId, sig)); assertEq(ret, ERC1271_INVALID); } @@ -124,7 +128,7 @@ abstract contract KernelERC1271Test is KernelTestBase { bytes memory sig = _permissionSignHash(personalHash, true); kernel.installModule(5, address(policy), abi.encode(hex"deadbeef", abi.encodePacked(permissionId))); kernel.installModule(6, address(signer), abi.encode(hex"deadbeef", abi.encodePacked(permissionId))); - bytes4 ret = kernel.isValidSignature(messageHash, abi.encodePacked(permissionId, sig)); + bytes4 ret = kernel.isValidSignature(messageHash, abi.encodePacked(bytes1(0x02), permissionId, sig)); assertEq(ret, ERC1271_MAGICVALUE); } diff --git a/test/KernelFactory.t.sol b/test/KernelFactory.t.sol index aec0881f..b582593c 100644 --- a/test/KernelFactory.t.sol +++ b/test/KernelFactory.t.sol @@ -9,7 +9,7 @@ import {KernelUUPS} from "src/KernelUUPS.sol"; import {KernelImmutableECDSA} from "src/KernelImmutableECDSA.sol"; import {Install, ValidationInfo} from "src/types/Structs.sol"; import {VALIDATION_TYPE_VALIDATOR} from "src/types/Constants.sol"; -import {ValidationId} from "src/types/Types.sol"; +import {ValidationId, PermissionId} from "src/types/Types.sol"; import {MockFallback} from "./mock/MockFallback.sol"; import {MockValidator} from "./mock/MockValidator.sol"; import {MockPolicy} from "./mock/MockPolicy.sol"; @@ -33,7 +33,7 @@ contract KernelFactoryTest is KernelTestBase { beneficiary = payable(makeAddr("Beneficiary")); policy = new MockPolicy(); signer = new MockSigner(); - permissionId = bytes20(keccak256(abi.encodePacked("Hello world"))); + permissionId = PermissionId.wrap(bytes4(keccak256(abi.encodePacked("Hello world")))); vm.txGasPrice(1); _initialize(); } @@ -103,7 +103,8 @@ contract KernelFactoryTest is KernelTestBase { bytes memory sig = enableSig(0, true, false, pkgs, _rootSignHash); Kernel k = factory.deployWithCall(initPkgs, 1, abi.encodeWithSelector(0xa706cd33, false, 0, pkgs, sig)); assertEq(address(k), address(kernel)); - ValidationInfo memory vInfo = k.validationInfo(ValidationId.wrap(bytes20(address(newValidator)))); + ValidationInfo memory vInfo = + k.validationInfo(ValidationId.wrap(bytes21(abi.encodePacked(bytes1(0x01), bytes20(address(newValidator)))))); assertTrue(vInfo.vType == VALIDATION_TYPE_VALIDATOR); } } diff --git a/test/KernelTestBase.sol b/test/KernelTestBase.sol index 3b157c70..3b280236 100644 --- a/test/KernelTestBase.sol +++ b/test/KernelTestBase.sol @@ -20,7 +20,7 @@ import {IValidator} from "src/interfaces/IERC7579Modules.sol"; import {console} from "forge-std/console.sol"; import {Received} from "src/types/Events.sol"; import {Install} from "src/types/Structs.sol"; -import {ValidationMode} from "src/types/Types.sol"; +import {ValidationMode, PermissionId} from "src/types/Types.sol"; abstract contract KernelTestBase is Test { IEntryPoint ep; @@ -35,7 +35,7 @@ abstract contract KernelTestBase is Test { address payable beneficiary; MockPolicy policy; MockSigner signer; - bytes20 permissionId; + PermissionId permissionId; uint256 permissionRevertIndex; KernelHelper helper; @@ -101,10 +101,10 @@ abstract contract KernelTestBase is Test { signatures[0] = hex"dead"; signatures[1] = hex"beef"; if (success || permissionRevertIndex != 0) { - policy.sudoSetValidSig(address(kernel), permissionId, hex"dead"); + policy.sudoSetValidSig(address(kernel), PermissionId.unwrap(permissionId), hex"dead"); } if (success || permissionRevertIndex != 1) { - signer.sudoSetValidSig(address(kernel), permissionId, hex"beef"); + signer.sudoSetValidSig(address(kernel), PermissionId.unwrap(permissionId), hex"beef"); } return abi.encode(signatures); @@ -115,10 +115,10 @@ abstract contract KernelTestBase is Test { signatures[0] = hex"dead"; signatures[1] = hex"beef"; if (success || permissionRevertIndex != 0) { - policy.sudoSetPass(address(kernel), permissionId, true); + policy.sudoSetPass(address(kernel), PermissionId.unwrap(permissionId), true); } if (success || permissionRevertIndex != 1) { - signer.sudoSetPass(address(kernel), permissionId, true); + signer.sudoSetPass(address(kernel), PermissionId.unwrap(permissionId), true); } return abi.encode(signatures); diff --git a/test/KernelUserOpTest.sol b/test/KernelUserOpTest.sol index 2668fccd..6157a20d 100644 --- a/test/KernelUserOpTest.sol +++ b/test/KernelUserOpTest.sol @@ -5,6 +5,7 @@ import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOper import {Kernel} from "src/Kernel.sol"; import {MockCallee} from "./mock/MockCallee.sol"; import {KernelTestBase} from "./KernelTestBase.sol"; +import {PermissionId} from "src/types/Types.sol"; abstract contract KernelUserOpTest is KernelTestBase { function test_executeuserop_root() external entryPointTest { @@ -187,7 +188,7 @@ abstract contract KernelUserOpTest is KernelTestBase { PackedUserOperation[] memory ops = new PackedUserOperation[](1); ops[0] = PackedUserOperation({ sender: address(kernel), - nonce: encodeNonce(false, false, false, bytes1(0x02), permissionId), + nonce: encodeNonce(false, false, false, bytes1(0x02), PermissionId.unwrap(permissionId)), initCode: hex"", callData: abi.encodeWithSelector( Kernel.execute.selector, bytes32(0), abi.encodePacked(address(callee), uint256(0), MockCallee.foo.selector) @@ -208,7 +209,7 @@ abstract contract KernelUserOpTest is KernelTestBase { PackedUserOperation[] memory ops = new PackedUserOperation[](1); ops[0] = PackedUserOperation({ sender: address(kernel), - nonce: encodeNonce(false, true, false, bytes1(0x02), permissionId), + nonce: encodeNonce(false, true, false, bytes1(0x02), PermissionId.unwrap(permissionId)), initCode: hex"", callData: abi.encodeWithSelector( Kernel.execute.selector, bytes32(0), abi.encodePacked(address(callee), uint256(0), MockCallee.foo.selector) @@ -231,7 +232,7 @@ abstract contract KernelUserOpTest is KernelTestBase { PackedUserOperation[] memory ops = new PackedUserOperation[](1); ops[0] = PackedUserOperation({ sender: address(kernel), - nonce: encodeNonce(false, true, false, bytes1(0x02), permissionId), + nonce: encodeNonce(false, true, false, bytes1(0x02), PermissionId.unwrap(permissionId)), initCode: hex"", callData: abi.encodeWithSelector( Kernel.execute.selector, bytes32(0), abi.encodePacked(address(callee), uint256(0), MockCallee.foo.selector) @@ -253,7 +254,7 @@ abstract contract KernelUserOpTest is KernelTestBase { PackedUserOperation[] memory ops = new PackedUserOperation[](1); ops[0] = PackedUserOperation({ sender: address(kernel), - nonce: encodeNonce(false, true, false, bytes1(0x02), permissionId), + nonce: encodeNonce(false, true, false, bytes1(0x02), PermissionId.unwrap(permissionId)), initCode: hex"", callData: abi.encodeWithSelector( Kernel.execute.selector, bytes32(0), abi.encodePacked(address(callee), uint256(0), MockCallee.foo.selector) @@ -275,7 +276,7 @@ abstract contract KernelUserOpTest is KernelTestBase { PackedUserOperation[] memory ops = new PackedUserOperation[](1); ops[0] = PackedUserOperation({ sender: address(kernel), - nonce: encodeNonce(false, true, false, bytes1(0x02), permissionId), + nonce: encodeNonce(false, true, false, bytes1(0x02), PermissionId.unwrap(permissionId)), initCode: hex"", callData: abi.encodeWithSelector( Kernel.execute.selector, bytes32(0), abi.encodePacked(address(callee), uint256(0), MockCallee.foo.selector) diff --git a/test/KernelValidatorTest.sol b/test/KernelValidatorTest.sol index cf5b9ae2..75d9bf06 100644 --- a/test/KernelValidatorTest.sol +++ b/test/KernelValidatorTest.sol @@ -1,11 +1,12 @@ pragma solidity ^0.8.0; import {Install, ValidationInfo} from "src/types/Structs.sol"; -import {ValidationId} from "src/types/Types.sol"; +import {ValidationId, PermissionId} from "src/types/Types.sol"; import {MockPolicy} from "./mock/MockPolicy.sol"; import {MockSigner} from "./mock/MockSigner.sol"; import {KernelTestBase} from "./KernelTestBase.sol"; import {InvalidNonce} from "src/types/Error.sol"; +import {getValidator, getPermissionId, validatorToIdentifier, permissionToIdentifier} from "src/lib/Utils.sol"; import { VALIDATION_TYPE_ROOT, VALIDATION_TYPE_VALIDATOR, @@ -13,6 +14,8 @@ import { ERC1271_MAGICVALUE } from "src/types/Constants.sol"; +import {console} from "forge-std/console.sol"; + abstract contract KernelValidatorTest is KernelTestBase { function test_set_valid_nonce() external unitTest { kernel.setValidNonceFrom(1); @@ -93,19 +96,20 @@ abstract contract KernelValidatorTest is KernelTestBase { function test_install_validator() external unitTest { assertTrue(kernel.supportsModule(1)); - ValidationId vId = ValidationId.wrap(bytes20(address(newValidator))); + ValidationId vId = validatorToIdentifier(newValidator); kernel.installModule(1, address(newValidator), abi.encode(hex"deadbeef", hex"")); ValidationInfo memory vInfo = kernel.validationInfo(vId); assertTrue(vInfo.vType == VALIDATION_TYPE_VALIDATOR); bytes4 ret = kernel.isValidSignature( - keccak256("Hello world"), abi.encodePacked(newValidator, _validatorSignHash(keccak256("Hello world"), true)) + keccak256("Hello world"), + abi.encodePacked(bytes1(0x01), newValidator, _validatorSignHash(keccak256("Hello world"), true)) ); assertEq(ret, ERC1271_MAGICVALUE); assertTrue(kernel.isModuleInstalled(1, address(newValidator), hex"")); } function test_uninstall_validator() external unitTest { - ValidationId vId = ValidationId.wrap(bytes20(address(newValidator))); + ValidationId vId = validatorToIdentifier(newValidator); kernel.installModule(1, address(newValidator), abi.encode(hex"deadbeef", hex"")); ValidationInfo memory vInfo = kernel.validationInfo(vId); assertTrue(vInfo.vType == VALIDATION_TYPE_VALIDATOR); @@ -117,7 +121,7 @@ abstract contract KernelValidatorTest is KernelTestBase { function test_install_permission() external unitTest { assertTrue(kernel.supportsModule(5)); assertTrue(kernel.supportsModule(6)); - ValidationId vId = ValidationId.wrap(permissionId); + ValidationId vId = permissionToIdentifier(permissionId); ValidationInfo memory vInfo = kernel.validationInfo(vId); assertTrue(vInfo.vType == VALIDATION_TYPE_ROOT); assertFalse(kernel.isModuleInstalled(5, address(policy), abi.encodePacked(permissionId))); @@ -126,7 +130,7 @@ abstract contract KernelValidatorTest is KernelTestBase { kernel.installModule(6, address(signer), abi.encode(hex"deadbeef", abi.encodePacked(permissionId))); bytes4 ret = kernel.isValidSignature( keccak256("Hello world"), - abi.encodePacked(permissionId, _permissionSignHash(keccak256("Hello world"), true)) + abi.encodePacked(bytes1(0x02), permissionId, _permissionSignHash(keccak256("Hello world"), true)) ); assertEq(ret, ERC1271_MAGICVALUE); assertTrue(kernel.isModuleInstalled(5, address(policy), abi.encodePacked(permissionId))); @@ -136,10 +140,14 @@ abstract contract KernelValidatorTest is KernelTestBase { function test_install_policy() external unitTest { assertTrue(kernel.supportsModule(5)); MockPolicy mock = new MockPolicy(); - ValidationId vId = ValidationId.wrap(permissionId); + ValidationId vId = permissionToIdentifier(permissionId); + console.log("PermissionId : "); + console.logBytes4(PermissionId.unwrap(permissionId)); ValidationInfo memory vInfo = kernel.validationInfo(vId); + console.log("ValidationId : "); + console.logBytes21(ValidationId.unwrap(vId)); assertTrue(vInfo.vType == VALIDATION_TYPE_ROOT); - kernel.installModule(5, address(mock), abi.encode(hex"deadbeef", abi.encodePacked(vId))); + kernel.installModule(5, address(mock), abi.encode(hex"deadbeef", abi.encodePacked(permissionId))); vInfo = kernel.validationInfo(vId); assertTrue(vInfo.vType == VALIDATION_TYPE_PERMISSION); assertTrue(kernel.isModuleInstalled(5, address(mock), abi.encodePacked(permissionId))); @@ -147,13 +155,13 @@ abstract contract KernelValidatorTest is KernelTestBase { function test_uninstall_policy() external unitTest { MockPolicy mock = new MockPolicy(); - ValidationId vId = ValidationId.wrap(permissionId); + ValidationId vId = permissionToIdentifier(permissionId); ValidationInfo memory vInfo = kernel.validationInfo(vId); assertTrue(vInfo.vType == VALIDATION_TYPE_ROOT); - kernel.installModule(5, address(mock), abi.encode(hex"deadbeef", abi.encodePacked(vId))); + kernel.installModule(5, address(mock), abi.encode(hex"deadbeef", abi.encodePacked(permissionId))); vInfo = kernel.validationInfo(vId); assertTrue(vInfo.vType == VALIDATION_TYPE_PERMISSION); - kernel.uninstallModule(5, address(mock), abi.encode(hex"deadbeef", abi.encodePacked(vId))); + kernel.uninstallModule(5, address(mock), abi.encode(hex"deadbeef", abi.encodePacked(permissionId))); vInfo = kernel.validationInfo(vId); assertTrue(vInfo.vType == VALIDATION_TYPE_ROOT); } @@ -161,10 +169,10 @@ abstract contract KernelValidatorTest is KernelTestBase { function test_install_signer() external unitTest { assertTrue(kernel.supportsModule(6)); MockSigner mock = new MockSigner(); - ValidationId vId = ValidationId.wrap(permissionId); + ValidationId vId = permissionToIdentifier(permissionId); ValidationInfo memory vInfo = kernel.validationInfo(vId); assertTrue(vInfo.vType == VALIDATION_TYPE_ROOT); - kernel.installModule(6, address(mock), abi.encode(hex"deadbeef", abi.encodePacked(vId))); + kernel.installModule(6, address(mock), abi.encode(hex"deadbeef", abi.encodePacked(permissionId))); vInfo = kernel.validationInfo(vId); assertTrue(vInfo.vType == VALIDATION_TYPE_PERMISSION); assertTrue(kernel.isModuleInstalled(6, address(mock), abi.encodePacked(permissionId))); @@ -172,14 +180,20 @@ abstract contract KernelValidatorTest is KernelTestBase { function test_uninstall_signer() external unitTest { MockSigner mock = new MockSigner(); - ValidationId vId = ValidationId.wrap(bytes20(keccak256(abi.encodePacked("deadbeef")))); + PermissionId pId = PermissionId.wrap(bytes4(keccak256(abi.encodePacked("deadbeef")))); + //PermissionId pId = PermissionId.wrap(bytes4(hex"deadbeef")); + console.log("PermissionId : "); + console.logBytes4(PermissionId.unwrap(pId)); + ValidationId vId = permissionToIdentifier(pId); + console.log("ValidationId : "); + console.logBytes21(ValidationId.unwrap(vId)); ValidationInfo memory vInfo = kernel.validationInfo(vId); assertTrue(vInfo.vType == VALIDATION_TYPE_ROOT); - kernel.installModule(6, address(mock), abi.encode(hex"deadbeef", abi.encodePacked(vId))); + kernel.installModule(6, address(mock), abi.encode(hex"deadbeef", abi.encodePacked(pId))); vInfo = kernel.validationInfo(vId); assertTrue(vInfo.vType == VALIDATION_TYPE_PERMISSION); assertTrue(vInfo.signer == address(mock)); - kernel.uninstallModule(6, address(mock), abi.encode(hex"deadbeef", abi.encodePacked(vId))); + kernel.uninstallModule(6, address(mock), abi.encode(hex"deadbeef", abi.encodePacked(pId))); vInfo = kernel.validationInfo(vId); assertTrue(vInfo.vType == VALIDATION_TYPE_ROOT); assertTrue(vInfo.signer == address(0)); From f67e36c1be0ad339d094c8dfda21470da160bcf2 Mon Sep 17 00:00:00 2001 From: leekt Date: Wed, 15 Oct 2025 01:11:20 +0900 Subject: [PATCH 088/121] feat: removed vType from storage --- snapshots/Kernel7702Test.json | 2 +- snapshots/KernelECDSATest.json | 2 +- snapshots/KernelFactoryTest.json | 2 +- snapshots/KernelImmutableECDSATest.json | 2 +- snapshots/KernelTest.json | 2 +- src/Kernel.sol | 9 +++---- src/core/ValidationManager.sol | 25 ++++++++++---------- src/types/Structs.sol | 5 ++-- test/KernelFactory.t.sol | 2 +- test/KernelValidatorTest.sol | 31 +++++++++++-------------- 10 files changed, 39 insertions(+), 43 deletions(-) diff --git a/snapshots/Kernel7702Test.json b/snapshots/Kernel7702Test.json index 8923d0d0..591bfbce 100644 --- a/snapshots/Kernel7702Test.json +++ b/snapshots/Kernel7702Test.json @@ -1,3 +1,3 @@ { - "Root - foo()": "168958" + "Root - foo()": "168935" } \ No newline at end of file diff --git a/snapshots/KernelECDSATest.json b/snapshots/KernelECDSATest.json index 5cbad5ba..9ce89493 100644 --- a/snapshots/KernelECDSATest.json +++ b/snapshots/KernelECDSATest.json @@ -1,3 +1,3 @@ { - "Root - foo()": "180594" + "Root - foo()": "178370" } \ No newline at end of file diff --git a/snapshots/KernelFactoryTest.json b/snapshots/KernelFactoryTest.json index ee3374f7..bdacaa8c 100644 --- a/snapshots/KernelFactoryTest.json +++ b/snapshots/KernelFactoryTest.json @@ -1,3 +1,3 @@ { - "Mock - deploy()": "181760" + "Mock - deploy()": "181717" } \ No newline at end of file diff --git a/snapshots/KernelImmutableECDSATest.json b/snapshots/KernelImmutableECDSATest.json index 16edffc7..2984be3c 100644 --- a/snapshots/KernelImmutableECDSATest.json +++ b/snapshots/KernelImmutableECDSATest.json @@ -1,3 +1,3 @@ { - "Root - foo()": "171938" + "Root - foo()": "171915" } \ No newline at end of file diff --git a/snapshots/KernelTest.json b/snapshots/KernelTest.json index 21e7caa6..12bea288 100644 --- a/snapshots/KernelTest.json +++ b/snapshots/KernelTest.json @@ -1,3 +1,3 @@ { - "Root - foo()": "194460" + "Root - foo()": "192236" } \ No newline at end of file diff --git a/src/Kernel.sol b/src/Kernel.sol index 9815aec2..1196e25f 100644 --- a/src/Kernel.sol +++ b/src/Kernel.sol @@ -9,7 +9,7 @@ import {parseNonce} from "./core/ValidationManager.sol"; import {ExecutionManager} from "./core/ExecutionManager.sol"; import {Lib4337} from "./lib/Lib4337.sol"; import {ERC1271} from "./lib/ERC1271.sol"; -import {getValidator, getPermissionId, validatorToIdentifier, permissionToIdentifier} from "./lib/Utils.sol"; +import {getType, getValidator, getPermissionId, validatorToIdentifier, permissionToIdentifier} from "./lib/Utils.sol"; import {LibERC7579} from "solady/accounts/LibERC7579.sol"; import { @@ -264,8 +264,9 @@ abstract contract Kernel is ModuleManager, ExecutionManager, IERC7579Account { ValidationId currentRoot = _validationStorage().root; if (removeCurrent) { ValidationId vId = _validationStorage().root; + ValidationType vType = getType(vId); ValidationInfo memory vInfo = _validationStorage().vInfo[vId]; - if (vInfo.vType == VALIDATION_TYPE_VALIDATOR) { + if (vType == VALIDATION_TYPE_VALIDATOR) { (bool success,) = address(getValidator(vId)).call(abi.encodeWithSelector(IModule.onUninstall.selector, uninstallData)); _uninstallValidator( @@ -274,7 +275,7 @@ abstract contract Kernel is ModuleManager, ExecutionManager, IERC7579Account { uninstallData, success ); - } else if (vInfo.vType == VALIDATION_TYPE_PERMISSION) { + } else if (vType == VALIDATION_TYPE_PERMISSION) { PermissionUninstallData calldata data; assembly { data := uninstallData.offset @@ -350,7 +351,7 @@ abstract contract Kernel is ModuleManager, ExecutionManager, IERC7579Account { { if (moduleTypeId == 1) { ValidationId vId = validatorToIdentifier(IValidator(module)); - return !(_validationStorage().vInfo[vId].vType == VALIDATION_TYPE_ROOT); + return _validationStorage().vInfo[vId].hook != address(0); } else if (moduleTypeId == 2) { return address(_executorConfig(IExecutor(module)).hook) != address(0); } else if (moduleTypeId == 3) { diff --git a/src/core/ValidationManager.sol b/src/core/ValidationManager.sol index b4fc14cf..014bc939 100644 --- a/src/core/ValidationManager.sol +++ b/src/core/ValidationManager.sol @@ -22,7 +22,7 @@ import { } from "../types/Constants.sol"; import {ValidationStorage, ValidationInfo, Install} from "../types/Structs.sol"; import {Lib4337} from "../lib/Lib4337.sol"; -import {getValidator, getPermissionId, validatorToIdentifier, permissionToIdentifier} from "../lib/Utils.sol"; +import {getType, getValidator, getPermissionId, validatorToIdentifier, permissionToIdentifier} from "../lib/Utils.sol"; import {console} from "forge-std/console.sol"; function parseNonce(uint256 nonce) pure returns (ValidationMode vMode, ValidationType vType, ValidationId vId) { @@ -70,6 +70,7 @@ abstract contract ValidationManager { // if _internalData is empty, skip the initialization if (_internalData.length == 0) { + $.vInfo[vId].hook = address(1); return; } // if not, first 20 bytes is the hook address @@ -89,8 +90,7 @@ abstract contract ValidationManager { require(_installSuccess, ModuleInstallFailed()); ValidationStorage storage $ = _validationStorage(); ValidationId vId = validatorToIdentifier(IValidator(_validator)); - require($.vInfo[vId].vType == VALIDATION_TYPE_ROOT, OccupiedValidationId()); - $.vInfo[vId].vType = VALIDATION_TYPE_VALIDATOR; + require($.vInfo[vId].hook == address(0), OccupiedValidationId()); _initializeValidation(vId, _internalData); } @@ -114,9 +114,8 @@ abstract contract ValidationManager { $ = _validationStorage().vInfo[vId]; if (installingPermission == ValidationId.wrap(bytes21(0))) { require(vId != ValidationId.wrap(bytes21(0)), "invalid validationId"); - require($.vType == ValidationType.wrap(0x00), "already taken"); + require($.hook == address(0), "already taken"); installingPermission = vId; - $.vType = VALIDATION_TYPE_PERMISSION; _initializeValidation(vId, _internalData[4:]); } else { require(installingPermission == vId, "permissionId should be consistent"); @@ -126,7 +125,7 @@ abstract contract ValidationManager { function _uninstallValidator(address _validator, bytes calldata _internalData, bool _uninstallSuccess) internal { ValidationStorage storage $ = _validationStorage(); ValidationId vId = validatorToIdentifier(IValidator(_validator)); - $.vInfo[vId].vType = VALIDATION_TYPE_ROOT; + $.vInfo[vId].hook = address(0); } function _uninstallPolicy(address _policy, bytes calldata _internalData, bool _uninstallSuccess) internal { @@ -142,7 +141,7 @@ abstract contract ValidationManager { $.policies.pop(); } if ($.signer == address(0)) { - $.vType = VALIDATION_TYPE_ROOT; + $.hook = address(0); } } @@ -156,7 +155,7 @@ abstract contract ValidationManager { require($.policies.length == 0, InvalidPermissionUninstallOrder()); require($.signer == _signer, InvalidPermissionId()); $.signer = address(0); - $.vType = VALIDATION_TYPE_ROOT; + $.hook = address(0); } function _checkValidation(ValidationType vType, ValidationId vId) @@ -168,15 +167,14 @@ abstract contract ValidationManager { ) { ValidationStorage storage $ = _validationStorage(); - if (vType == VALIDATION_TYPE_ROOT || $.vInfo[vId].vType == VALIDATION_TYPE_ROOT) { + if (vType == VALIDATION_TYPE_ROOT) { v = $.root; if (ValidationId.unwrap(v) == bytes21(0)) { return (v, _validateUserOpFallback); } - vType = $.vInfo[v].vType; + vType = getType(v); } else { v = vId; - require($.vInfo[vId].vType == vType, InvalidValidator()); } if (vType == VALIDATION_TYPE_PERMISSION) { @@ -195,11 +193,12 @@ abstract contract ValidationManager { return _verifyFallbackSignature(_hash, _signature) ? 0 : 1; } ValidationInfo storage vInfo = _validationStorage().vInfo[vId]; - if (vInfo.vType == VALIDATION_TYPE_VALIDATOR) { + ValidationType vType = getType(vId); + if (vType == VALIDATION_TYPE_VALIDATOR) { IValidator validator = getValidator(vId); validationData = validator.isValidSignatureWithSender(requester, _hash, _signature) == ERC1271_MAGICVALUE ? 0 : 1; - } else if (vInfo.vType == VALIDATION_TYPE_PERMISSION) { + } else if (vType == VALIDATION_TYPE_PERMISSION) { return _verifySignaturePermission(vId, vInfo, requester, _hash, _signature); } else { return 1; diff --git a/src/types/Structs.sol b/src/types/Structs.sol index e12febfe..90fe4afd 100644 --- a/src/types/Structs.sol +++ b/src/types/Structs.sol @@ -16,10 +16,9 @@ struct Uninstall { } struct ValidationInfo { - ValidationType vType; - address[] policies; - address signer; address hook; + address signer; + address[] policies; } struct ValidationStorage { diff --git a/test/KernelFactory.t.sol b/test/KernelFactory.t.sol index b582593c..3d3c5d38 100644 --- a/test/KernelFactory.t.sol +++ b/test/KernelFactory.t.sol @@ -105,6 +105,6 @@ contract KernelFactoryTest is KernelTestBase { assertEq(address(k), address(kernel)); ValidationInfo memory vInfo = k.validationInfo(ValidationId.wrap(bytes21(abi.encodePacked(bytes1(0x01), bytes20(address(newValidator)))))); - assertTrue(vInfo.vType == VALIDATION_TYPE_VALIDATOR); + assertTrue(vInfo.hook == address(1)); } } diff --git a/test/KernelValidatorTest.sol b/test/KernelValidatorTest.sol index 75d9bf06..8f442404 100644 --- a/test/KernelValidatorTest.sol +++ b/test/KernelValidatorTest.sol @@ -8,9 +8,6 @@ import {KernelTestBase} from "./KernelTestBase.sol"; import {InvalidNonce} from "src/types/Error.sol"; import {getValidator, getPermissionId, validatorToIdentifier, permissionToIdentifier} from "src/lib/Utils.sol"; import { - VALIDATION_TYPE_ROOT, - VALIDATION_TYPE_VALIDATOR, - VALIDATION_TYPE_PERMISSION, ERC1271_MAGICVALUE } from "src/types/Constants.sol"; @@ -99,7 +96,7 @@ abstract contract KernelValidatorTest is KernelTestBase { ValidationId vId = validatorToIdentifier(newValidator); kernel.installModule(1, address(newValidator), abi.encode(hex"deadbeef", hex"")); ValidationInfo memory vInfo = kernel.validationInfo(vId); - assertTrue(vInfo.vType == VALIDATION_TYPE_VALIDATOR); + assertTrue(vInfo.hook == address(1)); bytes4 ret = kernel.isValidSignature( keccak256("Hello world"), abi.encodePacked(bytes1(0x01), newValidator, _validatorSignHash(keccak256("Hello world"), true)) @@ -112,10 +109,10 @@ abstract contract KernelValidatorTest is KernelTestBase { ValidationId vId = validatorToIdentifier(newValidator); kernel.installModule(1, address(newValidator), abi.encode(hex"deadbeef", hex"")); ValidationInfo memory vInfo = kernel.validationInfo(vId); - assertTrue(vInfo.vType == VALIDATION_TYPE_VALIDATOR); + assertTrue(vInfo.hook == address(1)); kernel.uninstallModule(1, address(newValidator), abi.encode(hex"deadbeef", hex"")); vInfo = kernel.validationInfo(vId); - assertTrue(vInfo.vType == VALIDATION_TYPE_ROOT); + assertTrue(vInfo.hook == address(0)); } function test_install_permission() external unitTest { @@ -123,7 +120,7 @@ abstract contract KernelValidatorTest is KernelTestBase { assertTrue(kernel.supportsModule(6)); ValidationId vId = permissionToIdentifier(permissionId); ValidationInfo memory vInfo = kernel.validationInfo(vId); - assertTrue(vInfo.vType == VALIDATION_TYPE_ROOT); + assertTrue(vInfo.hook == address(0)); assertFalse(kernel.isModuleInstalled(5, address(policy), abi.encodePacked(permissionId))); assertFalse(kernel.isModuleInstalled(6, address(signer), abi.encodePacked(permissionId))); kernel.installModule(5, address(policy), abi.encode(hex"deadbeef", abi.encodePacked(permissionId))); @@ -146,10 +143,10 @@ abstract contract KernelValidatorTest is KernelTestBase { ValidationInfo memory vInfo = kernel.validationInfo(vId); console.log("ValidationId : "); console.logBytes21(ValidationId.unwrap(vId)); - assertTrue(vInfo.vType == VALIDATION_TYPE_ROOT); + assertTrue(vInfo.hook == address(0)); kernel.installModule(5, address(mock), abi.encode(hex"deadbeef", abi.encodePacked(permissionId))); vInfo = kernel.validationInfo(vId); - assertTrue(vInfo.vType == VALIDATION_TYPE_PERMISSION); + assertTrue(vInfo.hook == address(1)); assertTrue(kernel.isModuleInstalled(5, address(mock), abi.encodePacked(permissionId))); } @@ -157,13 +154,13 @@ abstract contract KernelValidatorTest is KernelTestBase { MockPolicy mock = new MockPolicy(); ValidationId vId = permissionToIdentifier(permissionId); ValidationInfo memory vInfo = kernel.validationInfo(vId); - assertTrue(vInfo.vType == VALIDATION_TYPE_ROOT); + assertTrue(vInfo.hook == address(0)); kernel.installModule(5, address(mock), abi.encode(hex"deadbeef", abi.encodePacked(permissionId))); vInfo = kernel.validationInfo(vId); - assertTrue(vInfo.vType == VALIDATION_TYPE_PERMISSION); + assertTrue(vInfo.hook == address(1)); kernel.uninstallModule(5, address(mock), abi.encode(hex"deadbeef", abi.encodePacked(permissionId))); vInfo = kernel.validationInfo(vId); - assertTrue(vInfo.vType == VALIDATION_TYPE_ROOT); + assertTrue(vInfo.hook == address(0)); } function test_install_signer() external unitTest { @@ -171,10 +168,10 @@ abstract contract KernelValidatorTest is KernelTestBase { MockSigner mock = new MockSigner(); ValidationId vId = permissionToIdentifier(permissionId); ValidationInfo memory vInfo = kernel.validationInfo(vId); - assertTrue(vInfo.vType == VALIDATION_TYPE_ROOT); + assertTrue(vInfo.hook == address(0)); kernel.installModule(6, address(mock), abi.encode(hex"deadbeef", abi.encodePacked(permissionId))); vInfo = kernel.validationInfo(vId); - assertTrue(vInfo.vType == VALIDATION_TYPE_PERMISSION); + assertTrue(vInfo.hook == address(1)); assertTrue(kernel.isModuleInstalled(6, address(mock), abi.encodePacked(permissionId))); } @@ -188,14 +185,14 @@ abstract contract KernelValidatorTest is KernelTestBase { console.log("ValidationId : "); console.logBytes21(ValidationId.unwrap(vId)); ValidationInfo memory vInfo = kernel.validationInfo(vId); - assertTrue(vInfo.vType == VALIDATION_TYPE_ROOT); + assertTrue(vInfo.hook == address(0)); kernel.installModule(6, address(mock), abi.encode(hex"deadbeef", abi.encodePacked(pId))); vInfo = kernel.validationInfo(vId); - assertTrue(vInfo.vType == VALIDATION_TYPE_PERMISSION); + assertTrue(vInfo.hook == address(1)); assertTrue(vInfo.signer == address(mock)); kernel.uninstallModule(6, address(mock), abi.encode(hex"deadbeef", abi.encodePacked(pId))); vInfo = kernel.validationInfo(vId); - assertTrue(vInfo.vType == VALIDATION_TYPE_ROOT); + assertTrue(vInfo.hook == address(0)); assertTrue(vInfo.signer == address(0)); } } From 6e3a5f58e659c8daeb975a86e14a85b17b28982f Mon Sep 17 00:00:00 2001 From: leekt Date: Wed, 15 Oct 2025 21:40:18 +0900 Subject: [PATCH 089/121] update: use vId 21 bytes as kernel v3 --- foundry.toml | 4 +- snapshots/Kernel7702Test.json | 2 +- snapshots/KernelECDSATest.json | 2 +- snapshots/KernelFactoryTest.json | 2 +- snapshots/KernelImmutableECDSATest.json | 2 +- snapshots/KernelTest.json | 2 +- src/Kernel.sol | 12 +- src/core/HookManager.sol | 4 + src/core/ModuleManager.sol | 10 + src/core/ValidationManager.sol | 14 +- test/Kernel.t.sol | 25 +- test/Kernel7702.t.sol | 8 +- test/KernelECDSA.t.sol | 8 +- test/KernelFactory.t.sol | 10 +- test/KernelHookTest.sol | 11 +- test/KernelImmutableECDSA.t.sol | 8 +- test/KernelSelectorTest.sol | 8 +- test/KernelTestBase.sol | 2 + test/KernelUserOpTest.sol | 6 + test/KernelValidatorTest.sol | 323 +++++++++++++++++++++--- 20 files changed, 387 insertions(+), 76 deletions(-) diff --git a/foundry.toml b/foundry.toml index 57d5992d..ee0fc192 100644 --- a/foundry.toml +++ b/foundry.toml @@ -4,7 +4,9 @@ out = "out" libs = ["lib"] via_ir = false # make this true optimizer = true -run = 200 +isolate = true + +run = 100000 evm_version = 'prague' solc_version = '0.8.30' diff --git a/snapshots/Kernel7702Test.json b/snapshots/Kernel7702Test.json index 591bfbce..1c8d5539 100644 --- a/snapshots/Kernel7702Test.json +++ b/snapshots/Kernel7702Test.json @@ -1,3 +1,3 @@ { - "Root - foo()": "168935" + "Root - foo()": "179326" } \ No newline at end of file diff --git a/snapshots/KernelECDSATest.json b/snapshots/KernelECDSATest.json index 9ce89493..b75e6d46 100644 --- a/snapshots/KernelECDSATest.json +++ b/snapshots/KernelECDSATest.json @@ -1,3 +1,3 @@ { - "Root - foo()": "178370" + "Root - foo()": "191085" } \ No newline at end of file diff --git a/snapshots/KernelFactoryTest.json b/snapshots/KernelFactoryTest.json index bdacaa8c..6be817d0 100644 --- a/snapshots/KernelFactoryTest.json +++ b/snapshots/KernelFactoryTest.json @@ -1,3 +1,3 @@ { - "Mock - deploy()": "181717" + "Mock - deploy()": "204548" } \ No newline at end of file diff --git a/snapshots/KernelImmutableECDSATest.json b/snapshots/KernelImmutableECDSATest.json index 2984be3c..2b9054fd 100644 --- a/snapshots/KernelImmutableECDSATest.json +++ b/snapshots/KernelImmutableECDSATest.json @@ -1,3 +1,3 @@ { - "Root - foo()": "171915" + "Root - foo()": "182341" } \ No newline at end of file diff --git a/snapshots/KernelTest.json b/snapshots/KernelTest.json index 12bea288..7f0aa5ea 100644 --- a/snapshots/KernelTest.json +++ b/snapshots/KernelTest.json @@ -1,3 +1,3 @@ { - "Root - foo()": "192236" + "Root - foo()": "208275" } \ No newline at end of file diff --git a/src/Kernel.sol b/src/Kernel.sol index 1196e25f..3166ed27 100644 --- a/src/Kernel.sol +++ b/src/Kernel.sol @@ -35,7 +35,7 @@ import { import {Received} from "./types/Events.sol"; import {VALIDATION_TYPE_ROOT, VALIDATION_TYPE_PERMISSION, VALIDATION_TYPE_VALIDATOR} from "./types/Constants.sol"; import {ValidationStorage, ValidationInfo} from "./types/Structs.sol"; - +import "forge-std/console.sol"; abstract contract Kernel is ModuleManager, ExecutionManager, IERC7579Account { IEntryPoint immutable ENTRYPOINT; @@ -119,13 +119,14 @@ abstract contract Kernel is ModuleManager, ExecutionManager, IERC7579Account { sig := signature.offset } validationData = _verifyInstallSignatureRaw(enableReplayable, sig.nonce, sig.packages, sig.enableSignature); + console.log("Enable :"); _install(sig.packages); signature = sig.userOpSignature; } ValidationStorage storage $ = _validationStorage(); // check if the call data is allowed by the validationId - if ($.vInfo[vId].hook != address(0)) { + if ($.vInfo[vId].hook > address(1)) { require( bytes4(userOp.callData[0:4]) == this.executeUserOp.selector && $.allowed[vId][bytes4(userOp.callData[4:])], @@ -172,7 +173,7 @@ abstract contract Kernel is ModuleManager, ExecutionManager, IERC7579Account { function _executeFromExecutor(bytes32 mode, bytes calldata executionData) internal executorHook - returns (bytes[] memory retyrbData) + returns (bytes[] memory returnData) { return _execute(mode, executionData); } @@ -313,6 +314,11 @@ abstract contract Kernel is ModuleManager, ExecutionManager, IERC7579Account { require(_verifyInstallSignature(replayable, nonce, packages, signature), InstallSignatureVerificationFailed()); _install(packages); } + + function installModule(Install[] calldata packages) external { + _onlyEntryPointOrSelf(); + _install(packages); + } fallback(bytes calldata) external payable returns (bytes memory) { return _fallback(); diff --git a/src/core/HookManager.sol b/src/core/HookManager.sol index 886fc6f6..cc727674 100644 --- a/src/core/HookManager.sol +++ b/src/core/HookManager.sol @@ -8,6 +8,10 @@ abstract contract HookManager { struct HookStorage { mapping(address => bool) enabled; } + + function _hookEnabled(IHook _hook) internal view virtual returns (bool) { + return _hookStorage().enabled[address(_hook)]; + } function _hookStorage() internal pure returns (HookStorage storage hs) { bytes32 slot = HOOK_MANAGER_STORAGE_SLOT; diff --git a/src/core/ModuleManager.sol b/src/core/ModuleManager.sol index a9dade48..f8af81f0 100644 --- a/src/core/ModuleManager.sol +++ b/src/core/ModuleManager.sol @@ -55,6 +55,10 @@ abstract contract ModuleManager is ValidationManager, ExecutorManager, HookManag } return (uint256(key) << 64) + seq; } + + function _hookEnabled(IHook _hook) internal view override(ValidationManager, HookManager) returns (bool) { + return HookManager._hookEnabled(_hook); + } function _initialized() internal view virtual returns (bool) { return _statelessInitializeCheck() || _statefulInitializeCheck(); @@ -172,6 +176,12 @@ abstract contract ModuleManager is ValidationManager, ExecutorManager, HookManag _installModule(pkg.moduleType, pkg.module, pkg.moduleData, pkg.internalData); } } + + require( + ValidationId.unwrap(installingPermission) == bytes21(0) + || _validationStorage().vInfo[installingPermission].signer != address(0), + "Permission Install not finished" + ); } function _install( diff --git a/src/core/ValidationManager.sol b/src/core/ValidationManager.sol index 014bc939..892b064f 100644 --- a/src/core/ValidationManager.sol +++ b/src/core/ValidationManager.sol @@ -10,7 +10,8 @@ import { InvalidPermissionUninstallOrder, InvalidPermissionUninstallOrder, InvalidPermissionId, - InvalidValidator + InvalidValidator, + NotInstalled } from "../types/Error.sol"; import {ValidationId, PermissionId, ValidationType, ValidationMode} from "../types/Types.sol"; import { @@ -23,7 +24,6 @@ import { import {ValidationStorage, ValidationInfo, Install} from "../types/Structs.sol"; import {Lib4337} from "../lib/Lib4337.sol"; import {getType, getValidator, getPermissionId, validatorToIdentifier, permissionToIdentifier} from "../lib/Utils.sol"; -import {console} from "forge-std/console.sol"; function parseNonce(uint256 nonce) pure returns (ValidationMode vMode, ValidationType vType, ValidationId vId) { // 2bytes mode (1byte currentMode, 1byte type) @@ -35,8 +35,11 @@ function parseNonce(uint256 nonce) pure returns (ValidationMode vMode, Validatio } abstract contract ValidationManager { + error InvalidVid(ValidationId vId); ValidationId transient installingPermission; + function _hookEnabled(IHook _hook) internal view virtual returns (bool); + function root() external view returns (ValidationId) { ValidationStorage storage $ = _validationStorage(); return $.root; @@ -75,7 +78,8 @@ abstract contract ValidationManager { } // if not, first 20 bytes is the hook address address hook = address(bytes20(_internalData[0:20])); - $.vInfo[vId].hook = hook; + require(hook == address(0) || hook == address(1) || _hookEnabled(IHook(hook)), NotInstalled()); + $.vInfo[vId].hook = hook == address(0) ? address(1) : hook; _internalData = _internalData[20:]; // then the rest is the allowed selectors @@ -114,7 +118,6 @@ abstract contract ValidationManager { $ = _validationStorage().vInfo[vId]; if (installingPermission == ValidationId.wrap(bytes21(0))) { require(vId != ValidationId.wrap(bytes21(0)), "invalid validationId"); - require($.hook == address(0), "already taken"); installingPermission = vId; _initializeValidation(vId, _internalData[4:]); } else { @@ -177,6 +180,9 @@ abstract contract ValidationManager { v = vId; } + ValidationInfo storage info = _validationStorage().vInfo[v]; + require(info.hook > address(0), InvalidVid(v)); + if (vType == VALIDATION_TYPE_PERMISSION) { validateUserOp = _validateUserOpPermission; } else { diff --git a/test/Kernel.t.sol b/test/Kernel.t.sol index f0dfa090..bfeee0d0 100644 --- a/test/Kernel.t.sol +++ b/test/Kernel.t.sol @@ -50,6 +50,7 @@ contract KernelTest is beneficiary = payable(makeAddr("Beneficiary")); policy = new MockPolicy(); signer = new MockSigner(); + hook = new MockHook(); permissionId = PermissionId.wrap(bytes4(keccak256(abi.encodePacked("Hello world")))); _initialize(); } @@ -77,7 +78,7 @@ contract KernelTest is } function test_install_packages_with_signature() external unitTest { - Install[] memory packages = new Install[](2); + Install[] memory packages = new Install[](3); packages[0] = Install({moduleType: 1, module: address(newValidator), internalData: hex"", moduleData: hex""}); packages[1] = Install({ moduleType: 5, @@ -85,11 +86,17 @@ contract KernelTest is internalData: abi.encodePacked(permissionId), moduleData: hex"" }); + packages[2] = Install({ + moduleType: 6, + module: address(signer), + internalData: abi.encodePacked(permissionId), + moduleData: hex"" + }); kernel.installModule(false, 0, packages, enableSig(0, true, false, packages, _rootSignHash)); } function test_install_packages_with_signature_replayable() external unitTest { - Install[] memory packages = new Install[](2); + Install[] memory packages = new Install[](3); packages[0] = Install({moduleType: 1, module: address(newValidator), internalData: hex"", moduleData: hex""}); packages[1] = Install({ moduleType: 5, @@ -97,6 +104,12 @@ contract KernelTest is internalData: abi.encodePacked(permissionId), moduleData: hex"" }); + packages[2] = Install({ + moduleType: 6, + module: address(signer), + internalData: abi.encodePacked(permissionId), + moduleData: hex"" + }); kernel.installModule(true, 0, packages, enableSig(0, true, true, packages, _rootSignHash)); } @@ -109,17 +122,15 @@ contract KernelTest is } function test_install_invalid() external unitTest { - MockHook mockHook = new MockHook(); vm.expectRevert(NotImplemented.selector); - kernel.installModule(10, address(mockHook), abi.encode(hex"", "")); + kernel.installModule(10, address(hook), abi.encode(hex"", "")); vm.expectRevert(NotImplemented.selector); - kernel.isModuleInstalled(10, address(mockHook), abi.encodePacked(permissionId)); + kernel.isModuleInstalled(10, address(hook), abi.encodePacked(permissionId)); } function test_uninstall_invalid() external unitTest { - MockHook mockHook = new MockHook(); vm.expectRevert(NotImplemented.selector); - kernel.uninstallModule(10, address(mockHook), abi.encode(hex"", "")); + kernel.uninstallModule(10, address(hook), abi.encode(hex"", "")); } function test_supports_module() external unitTest { diff --git a/test/Kernel7702.t.sol b/test/Kernel7702.t.sol index b892df3e..f106fa46 100644 --- a/test/Kernel7702.t.sol +++ b/test/Kernel7702.t.sol @@ -51,7 +51,7 @@ contract Kernel7702Test is KernelTest { } function test_change_root_check_vId_0() external unitTest { - Install[] memory packages = new Install[](2); + Install[] memory packages = new Install[](3); packages[0] = Install({moduleType: 1, module: address(newValidator), internalData: hex"", moduleData: hex""}); packages[1] = Install({ moduleType: 5, @@ -59,6 +59,12 @@ contract Kernel7702Test is KernelTest { internalData: abi.encodePacked(permissionId), moduleData: hex"" }); + packages[2] = Install({ + moduleType: 6, + module: address(signer), + internalData: abi.encodePacked(permissionId), + moduleData: hex"" + }); kernel.setRoot(packages, false, hex""); diff --git a/test/KernelECDSA.t.sol b/test/KernelECDSA.t.sol index 91ec546d..f81c9d12 100644 --- a/test/KernelECDSA.t.sol +++ b/test/KernelECDSA.t.sol @@ -54,7 +54,7 @@ contract KernelECDSATest is KernelTest { } function test_change_root_check_vId_0() external unitTest { - Install[] memory packages = new Install[](2); + Install[] memory packages = new Install[](3); packages[0] = Install({moduleType: 1, module: address(newValidator), internalData: hex"", moduleData: hex""}); packages[1] = Install({ moduleType: 5, @@ -62,6 +62,12 @@ contract KernelECDSATest is KernelTest { internalData: abi.encodePacked(permissionId), moduleData: hex"" }); + packages[2] = Install({ + moduleType: 6, + module: address(signer), + internalData: abi.encodePacked(permissionId), + moduleData: hex"" + }); kernel.installModule(false, 0, packages, enableSig(0, true, false, packages, _rootSignHash)); kernel.setRoot(ValidationId.wrap(bytes20(address(newValidator)))); diff --git a/test/KernelFactory.t.sol b/test/KernelFactory.t.sol index 3d3c5d38..dbc6c9a2 100644 --- a/test/KernelFactory.t.sol +++ b/test/KernelFactory.t.sol @@ -62,14 +62,20 @@ contract KernelFactoryTest is KernelTestBase { } function test_deploy_root_permission() external unitTest { - Install[] memory pkgs = new Install[](2); + Install[] memory pkgs = new Install[](3); pkgs[0] = Install({ moduleType: 5, module: address(policy), internalData: abi.encodePacked(permissionId), moduleData: hex"" }); - pkgs[1] = Install({moduleType: 1, module: address(newValidator), internalData: hex"", moduleData: hex""}); + pkgs[1] = Install({ + moduleType: 6, + module: address(signer), + internalData: abi.encodePacked(permissionId), + moduleData: hex"" + }); + pkgs[2] = Install({moduleType: 1, module: address(newValidator), internalData: hex"", moduleData: hex""}); Kernel k = factory.deploy(pkgs, 1); assertEq(k.accountId(), "kernel.v0.4"); assertEq(k.registry(), address(0)); diff --git a/test/KernelHookTest.sol b/test/KernelHookTest.sol index 26d4580f..bcb4765e 100644 --- a/test/KernelHookTest.sol +++ b/test/KernelHookTest.sol @@ -1,19 +1,16 @@ pragma solidity ^0.8.0; -import {MockHook} from "./mock/MockHook.sol"; import {KernelTestBase} from "./KernelTestBase.sol"; abstract contract KernelHookTest is KernelTestBase { function test_install_hook() external unitTest { assertTrue(kernel.supportsModule(4)); - MockHook mockHook = new MockHook(); - kernel.installModule(4, address(mockHook), abi.encode(hex"", "")); - assertTrue(kernel.isModuleInstalled(4, address(mockHook), hex"")); + kernel.installModule(4, address(hook), abi.encode(hex"", "")); + assertTrue(kernel.isModuleInstalled(4, address(hook), hex"")); } function test_uninstall_hook() external unitTest { - MockHook mockHook = new MockHook(); - kernel.installModule(4, address(mockHook), abi.encode(hex"", "")); - kernel.uninstallModule(4, address(mockHook), abi.encode(hex"", "")); + kernel.installModule(4, address(hook), abi.encode(hex"", "")); + kernel.uninstallModule(4, address(hook), abi.encode(hex"", "")); } } diff --git a/test/KernelImmutableECDSA.t.sol b/test/KernelImmutableECDSA.t.sol index 2935a8ef..587f7e07 100644 --- a/test/KernelImmutableECDSA.t.sol +++ b/test/KernelImmutableECDSA.t.sol @@ -43,7 +43,7 @@ contract KernelImmutableECDSATest is KernelTest { } function test_change_root_check_vId_0() external unitTest { - Install[] memory packages = new Install[](2); + Install[] memory packages = new Install[](3); packages[0] = Install({moduleType: 1, module: address(newValidator), internalData: hex"", moduleData: hex""}); packages[1] = Install({ moduleType: 5, @@ -51,6 +51,12 @@ contract KernelImmutableECDSATest is KernelTest { internalData: abi.encodePacked(permissionId), moduleData: hex"" }); + packages[2] = Install({ + moduleType: 6, + module: address(signer), + internalData: abi.encodePacked(permissionId), + moduleData: hex"" + }); kernel.installModule(false, 0, packages, enableSig(0, true, false, packages, _rootSignHash)); kernel.setRoot(ValidationId.wrap(bytes20(address(newValidator)))); diff --git a/test/KernelSelectorTest.sol b/test/KernelSelectorTest.sol index a117a268..5506e8b6 100644 --- a/test/KernelSelectorTest.sol +++ b/test/KernelSelectorTest.sol @@ -2,7 +2,6 @@ pragma solidity ^0.8.0; import {SelectorManager} from "src/core/SelectorManager.sol"; import {MockFallback} from "./mock/MockFallback.sol"; -import {MockHook} from "./mock/MockHook.sol"; import {CallType} from "src/types/Types.sol"; import {KernelTestBase} from "./KernelTestBase.sol"; import {InvalidSelector} from "src/types/Error.sol"; @@ -36,13 +35,12 @@ abstract contract KernelSelectorTest is KernelTestBase { } function test_install_selector_call_withhook() external unitTest { - MockHook mockHook = new MockHook(); - kernel.installModule(4, address(mockHook), abi.encode(hex"", "")); + kernel.installModule(4, address(hook), abi.encode(hex"", "")); kernel.installModule( 3, address(mockFallback), abi.encode( - hex"deadbeef", abi.encodePacked(MockFallback.fallbackFunction.selector, bytes1(0x00), address(mockHook)) + hex"deadbeef", abi.encodePacked(MockFallback.fallbackFunction.selector, bytes1(0x00), address(hook)) ) ); vm.expectEmit(address(mockFallback)); @@ -51,7 +49,7 @@ abstract contract KernelSelectorTest is KernelTestBase { assertEq(res, 100); SelectorManager.SelectorConfig memory c = kernel.selectorConfig(MockFallback.fallbackFunction.selector); assertEq(address(c.target), address(mockFallback)); - assertEq(address(c.hook), address(mockHook)); + assertEq(address(c.hook), address(hook)); assertTrue(c.callType == CallType.wrap(bytes1(0x00))); } diff --git a/test/KernelTestBase.sol b/test/KernelTestBase.sol index 3b280236..7f450c68 100644 --- a/test/KernelTestBase.sol +++ b/test/KernelTestBase.sol @@ -16,6 +16,7 @@ import {MockERC1155} from "./mock/MockERC1155.sol"; import {MockCallee} from "./mock/MockCallee.sol"; import {MockContractETH} from "./mock/MockContractETH.sol"; import {MockKernel} from "./mock/MockKernel.sol"; +import {MockHook} from "./mock/MockHook.sol"; import {IValidator} from "src/interfaces/IERC7579Modules.sol"; import {console} from "forge-std/console.sol"; import {Received} from "src/types/Events.sol"; @@ -35,6 +36,7 @@ abstract contract KernelTestBase is Test { address payable beneficiary; MockPolicy policy; MockSigner signer; + MockHook hook; PermissionId permissionId; uint256 permissionRevertIndex; KernelHelper helper; diff --git a/test/KernelUserOpTest.sol b/test/KernelUserOpTest.sol index 6157a20d..0f55398a 100644 --- a/test/KernelUserOpTest.sol +++ b/test/KernelUserOpTest.sol @@ -6,6 +6,7 @@ import {Kernel} from "src/Kernel.sol"; import {MockCallee} from "./mock/MockCallee.sol"; import {KernelTestBase} from "./KernelTestBase.sol"; import {PermissionId} from "src/types/Types.sol"; +import {validatorToIdentifier} from "src/lib/Utils.sol"; abstract contract KernelUserOpTest is KernelTestBase { function test_executeuserop_root() external entryPointTest { @@ -137,8 +138,13 @@ abstract contract KernelUserOpTest is KernelTestBase { ); ep.handleOps(ops, beneficiary); assertEq(callee.bar(), 1); + assertEq(kernel.validationInfo(validatorToIdentifier(newValidator)).hook, address(1)); } + function test_userop_validator_hook_failed_prehook() external entryPointTest {} + + function test_userop_validator_hook_failed_posthook() external entryPointTest {} + function test_userop_validator_aa24_enable_fail_wrong_signature() external entryPointTest { PackedUserOperation[] memory ops = new PackedUserOperation[](1); ops[0] = PackedUserOperation({ diff --git a/test/KernelValidatorTest.sol b/test/KernelValidatorTest.sol index 8f442404..e625e293 100644 --- a/test/KernelValidatorTest.sol +++ b/test/KernelValidatorTest.sol @@ -1,24 +1,103 @@ pragma solidity ^0.8.0; import {Install, ValidationInfo} from "src/types/Structs.sol"; +import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol"; import {ValidationId, PermissionId} from "src/types/Types.sol"; import {MockPolicy} from "./mock/MockPolicy.sol"; import {MockSigner} from "./mock/MockSigner.sol"; +import {MockCallee} from "./mock/MockCallee.sol"; import {KernelTestBase} from "./KernelTestBase.sol"; -import {InvalidNonce} from "src/types/Error.sol"; -import {getValidator, getPermissionId, validatorToIdentifier, permissionToIdentifier} from "src/lib/Utils.sol"; +import {InvalidNonce, NotInstalled} from "src/types/Error.sol"; import { + VALIDATION_TYPE_ROOT, + VALIDATION_TYPE_VALIDATOR, + VALIDATION_TYPE_PERMISSION, ERC1271_MAGICVALUE } from "src/types/Constants.sol"; +import {permissionToIdentifier} from "src/lib/Utils.sol"; import {console} from "forge-std/console.sol"; abstract contract KernelValidatorTest is KernelTestBase { + function _sendUserOpValidator(bool success, bool useHook) internal { + PackedUserOperation[] memory ops = new PackedUserOperation[](1); + ops[0] = PackedUserOperation({ + sender: address(kernel), + nonce: encodeNonce(false, false, false, bytes1(0x01), bytes20(address(newValidator))), + initCode: hex"", + callData: useHook + ? abi.encodePacked( + kernel.executeUserOp.selector, + abi.encodeWithSelector( + kernel.execute.selector, + bytes32(0), + abi.encodePacked(address(callee), uint256(0), MockCallee.foo.selector) + ) + ) + : abi.encodeWithSelector( + kernel.execute.selector, bytes32(0), abi.encodePacked(address(callee), uint256(0), MockCallee.foo.selector) + ), + accountGasLimits: bytes32(abi.encodePacked(uint128(1000000), uint128(1000000))), + preVerificationGas: 1000000, + gasFees: bytes32(abi.encodePacked(uint128(1), uint128(1))), + paymasterAndData: hex"", + signature: hex"" + }); + ops[0].signature = _validatorSignUserOp(ops[0], true, false); + if (useHook) { + assertEq(hook.preHookData(address(kernel)), hex""); + } + if (!success) { + vm.expectRevert(); + } + ep.handleOps(ops, beneficiary); + if (useHook && success) { + assertTrue(hook.preHookData(address(kernel)).length != 0); + } + } + + function _sendUserOpPermission(bool success, bool useHook) internal { + PackedUserOperation[] memory ops = new PackedUserOperation[](1); + ops[0] = PackedUserOperation({ + sender: address(kernel), + nonce: encodeNonce(false, false, false, bytes1(0x02), PermissionId.unwrap(permissionId)), + initCode: hex"", + callData: useHook + ? abi.encodePacked( + kernel.executeUserOp.selector, + abi.encodeWithSelector( + kernel.execute.selector, + bytes32(0), + abi.encodePacked(address(callee), uint256(0), MockCallee.foo.selector) + ) + ) + : abi.encodeWithSelector( + kernel.execute.selector, bytes32(0), abi.encodePacked(address(callee), uint256(0), MockCallee.foo.selector) + ), + accountGasLimits: bytes32(abi.encodePacked(uint128(1000000), uint128(1000000))), + preVerificationGas: 1000000, + gasFees: bytes32(abi.encodePacked(uint128(1), uint128(1))), + paymasterAndData: hex"", + signature: hex"" + }); + ops[0].signature = _permissionSignUserOp(ops[0], true, false); + if (useHook) { + assertEq(hook.preHookData(address(kernel)), hex""); + } + if (!success) { + vm.expectRevert(); + } + ep.handleOps(ops, beneficiary); + if (useHook && success) { + assertTrue(hook.preHookData(address(kernel)).length != 0); + } + } + function test_set_valid_nonce() external unitTest { kernel.setValidNonceFrom(1); assertEq(kernel.validNonceFrom(), 1); - Install[] memory packages = new Install[](2); + Install[] memory packages = new Install[](3); packages[0] = Install({moduleType: 1, module: address(newValidator), internalData: hex"", moduleData: hex""}); packages[1] = Install({ moduleType: 5, @@ -26,6 +105,12 @@ abstract contract KernelValidatorTest is KernelTestBase { internalData: abi.encodePacked(permissionId), moduleData: hex"" }); + packages[2] = Install({ + moduleType: 6, + module: address(signer), + internalData: abi.encodePacked(permissionId), + moduleData: hex"" + }); bytes memory sig = enableSig(0, true, false, packages, _rootSignHash); vm.expectRevert(InvalidNonce.selector); kernel.installModule(false, 0, packages, sig); @@ -40,7 +125,7 @@ abstract contract KernelValidatorTest is KernelTestBase { kernel.setNonce(0, 1); assertEq(kernel.nonce(0), 1); - Install[] memory packages = new Install[](2); + Install[] memory packages = new Install[](3); packages[0] = Install({moduleType: 1, module: address(newValidator), internalData: hex"", moduleData: hex""}); packages[1] = Install({ moduleType: 5, @@ -48,6 +133,12 @@ abstract contract KernelValidatorTest is KernelTestBase { internalData: abi.encodePacked(permissionId), moduleData: hex"" }); + packages[2] = Install({ + moduleType: 6, + module: address(signer), + internalData: abi.encodePacked(permissionId), + moduleData: hex"" + }); bytes memory sig = enableSig(0, true, false, packages, _rootSignHash); vm.expectRevert(InvalidNonce.selector); kernel.installModule(false, 0, packages, sig); @@ -64,7 +155,7 @@ abstract contract KernelValidatorTest is KernelTestBase { } function test_change_root() external unitTest { - Install[] memory packages = new Install[](2); + Install[] memory packages = new Install[](3); packages[0] = Install({moduleType: 1, module: address(newValidator), internalData: hex"", moduleData: hex""}); packages[1] = Install({ moduleType: 5, @@ -72,49 +163,108 @@ abstract contract KernelValidatorTest is KernelTestBase { internalData: abi.encodePacked(permissionId), moduleData: hex"" }); - - kernel.setRoot(packages, false, hex""); - } - - function test_change_root_remove_previous_validator() external unitTest { - vm.skip(is7702); - vm.skip(isImmutable); - Install[] memory packages = new Install[](2); - packages[0] = Install({moduleType: 1, module: address(newValidator), internalData: hex"", moduleData: hex""}); - packages[1] = Install({ - moduleType: 5, - module: address(policy), + packages[2] = Install({ + moduleType: 6, + module: address(signer), internalData: abi.encodePacked(permissionId), moduleData: hex"" }); + kernel.installModule(false, 0, packages, enableSig(0, true, false, packages, _rootSignHash)); - kernel.setRoot(packages, true, hex""); + kernel.setRoot(ValidationId.wrap(bytes20(address(newValidator)))); } function test_install_validator() external unitTest { assertTrue(kernel.supportsModule(1)); - ValidationId vId = validatorToIdentifier(newValidator); + ValidationId vId = ValidationId.wrap(bytes20(address(newValidator))); kernel.installModule(1, address(newValidator), abi.encode(hex"deadbeef", hex"")); ValidationInfo memory vInfo = kernel.validationInfo(vId); - assertTrue(vInfo.hook == address(1)); + assertTrue(vInfo.hook == address(0)); bytes4 ret = kernel.isValidSignature( - keccak256("Hello world"), - abi.encodePacked(bytes1(0x01), newValidator, _validatorSignHash(keccak256("Hello world"), true)) + keccak256("Hello world"), abi.encodePacked(bytes1(0x01), newValidator, _validatorSignHash(keccak256("Hello world"), true)) + ); + assertEq(ret, ERC1271_MAGICVALUE); + assertTrue(kernel.isModuleInstalled(1, address(newValidator), hex"")); + } + + function test_install_validator_with_selector() external unitTest { + assertTrue(kernel.supportsModule(1)); + ValidationId vId = ValidationId.wrap(bytes20(address(newValidator))); + kernel.installModule( + 1, address(newValidator), abi.encode(hex"deadbeef", abi.encodePacked(address(0), kernel.execute.selector)) + ); + ValidationInfo memory vInfo = kernel.validationInfo(vId); + assertTrue(vInfo.hook == address(0)); + bytes4 ret = kernel.isValidSignature( + keccak256("Hello world"), abi.encodePacked(bytes1(0x01), newValidator, _validatorSignHash(keccak256("Hello world"), true)) ); assertEq(ret, ERC1271_MAGICVALUE); assertTrue(kernel.isModuleInstalled(1, address(newValidator), hex"")); + + _sendUserOpValidator(true, false); + } + + function test_install_validator_with_other_selector() external unitTest { + assertTrue(kernel.supportsModule(1)); + ValidationId vId = ValidationId.wrap(bytes20(address(newValidator))); + kernel.installModule( + 1, address(newValidator), abi.encode(hex"deadbeef", abi.encodePacked(address(0), kernel.setNonce.selector)) + ); + ValidationInfo memory vInfo = kernel.validationInfo(vId); + assertTrue(vInfo.hook == address(0)); + bytes4 ret = kernel.isValidSignature( + keccak256("Hello world"), abi.encodePacked(bytes1(0x01), newValidator, _validatorSignHash(keccak256("Hello world"), true)) + ); + assertEq(ret, ERC1271_MAGICVALUE); + assertTrue(kernel.isModuleInstalled(1, address(newValidator), hex"")); + + _sendUserOpValidator(false, false); + } + + function test_install_validator_with_hook() external unitTest { + assertTrue(kernel.supportsModule(4)); + kernel.installModule(4, address(hook), abi.encode(hex"", "")); + assertTrue(kernel.supportsModule(1)); + ValidationId vId = ValidationId.wrap(bytes20(address(newValidator))); + kernel.installModule( + 1, + address(newValidator), + abi.encode(hex"deadbeef", abi.encodePacked(address(hook), kernel.execute.selector)) + ); + ValidationInfo memory vInfo = kernel.validationInfo(vId); + assertTrue(vInfo.hook == address(0)); + bytes4 ret = kernel.isValidSignature( + keccak256("Hello world"), abi.encodePacked(bytes1(0x01), newValidator, _validatorSignHash(keccak256("Hello world"), true)) + ); + assertEq(ret, ERC1271_MAGICVALUE); + assertTrue(kernel.isModuleInstalled(1, address(newValidator), hex"")); + + _sendUserOpValidator(true, true); + } + + function test_install_validator_with_hook_notinstalled() external unitTest { + assertTrue(kernel.supportsModule(4)); + assertTrue(kernel.supportsModule(1)); + ValidationId vId = ValidationId.wrap(bytes20(address(newValidator))); + vm.expectRevert(NotInstalled.selector); + kernel.installModule( + 1, + address(newValidator), + abi.encode(hex"deadbeef", abi.encodePacked(address(hook), kernel.execute.selector)) + ); } function test_uninstall_validator() external unitTest { - ValidationId vId = validatorToIdentifier(newValidator); + ValidationId vId = ValidationId.wrap(bytes20(address(newValidator))); kernel.installModule(1, address(newValidator), abi.encode(hex"deadbeef", hex"")); ValidationInfo memory vInfo = kernel.validationInfo(vId); - assertTrue(vInfo.hook == address(1)); + assertTrue(vInfo.hook == address(0)); kernel.uninstallModule(1, address(newValidator), abi.encode(hex"deadbeef", hex"")); vInfo = kernel.validationInfo(vId); assertTrue(vInfo.hook == address(0)); } + /// forge-config: default.isolate = true function test_install_permission() external unitTest { assertTrue(kernel.supportsModule(5)); assertTrue(kernel.supportsModule(6)); @@ -123,8 +273,20 @@ abstract contract KernelValidatorTest is KernelTestBase { assertTrue(vInfo.hook == address(0)); assertFalse(kernel.isModuleInstalled(5, address(policy), abi.encodePacked(permissionId))); assertFalse(kernel.isModuleInstalled(6, address(signer), abi.encodePacked(permissionId))); - kernel.installModule(5, address(policy), abi.encode(hex"deadbeef", abi.encodePacked(permissionId))); - kernel.installModule(6, address(signer), abi.encode(hex"deadbeef", abi.encodePacked(permissionId))); + Install[] memory pkgs = new Install[](2); + pkgs[0] = Install({ + moduleType: 5, + module: address(policy), + moduleData: hex"deadbeef", + internalData: abi.encodePacked(permissionId) + }); + pkgs[1] = Install({ + moduleType: 6, + module: address(signer), + moduleData: hex"deadbeef", + internalData: abi.encodePacked(permissionId) + }); + kernel.installModule(pkgs); bytes4 ret = kernel.isValidSignature( keccak256("Hello world"), abi.encodePacked(bytes1(0x02), permissionId, _permissionSignHash(keccak256("Hello world"), true)) @@ -134,15 +296,74 @@ abstract contract KernelValidatorTest is KernelTestBase { assertTrue(kernel.isModuleInstalled(6, address(signer), abi.encodePacked(permissionId))); } + /// forge-config: default.isolate = true + function test_install_permission_with_hook() external unitTest { + assertTrue(kernel.supportsModule(4)); + kernel.installModule(4, address(hook), abi.encode(hex"", "")); + assertTrue(kernel.supportsModule(5)); + assertTrue(kernel.supportsModule(6)); + ValidationId vId = permissionToIdentifier(permissionId); + ValidationInfo memory vInfo = kernel.validationInfo(vId); + assertTrue(vInfo.hook == address(0)); + assertFalse(kernel.isModuleInstalled(5, address(policy), abi.encodePacked(permissionId))); + assertFalse(kernel.isModuleInstalled(6, address(signer), abi.encodePacked(permissionId))); + Install[] memory pkgs = new Install[](2); + pkgs[0] = Install({ + moduleType: 5, + module: address(policy), + moduleData: hex"deadbeef", + internalData: abi.encodePacked(permissionId, hook, kernel.execute.selector) + }); + pkgs[1] = Install({ + moduleType: 6, + module: address(signer), + moduleData: hex"deadbeef", + internalData: abi.encodePacked(permissionId) + }); + kernel.installModule(pkgs); + bytes4 ret = kernel.isValidSignature( + keccak256("Hello world"), + abi.encodePacked(bytes1(0x02), permissionId, _permissionSignHash(keccak256("Hello world"), true)) + ); + assertEq(ret, ERC1271_MAGICVALUE); + assertTrue(kernel.isModuleInstalled(5, address(policy), abi.encodePacked(permissionId))); + assertTrue(kernel.isModuleInstalled(6, address(signer), abi.encodePacked(permissionId))); + + _sendUserOpPermission(true, true); + } + + /// forge-config: default.isolate = true + function test_install_permission_with_hook_notinstalled() external unitTest { + assertTrue(kernel.supportsModule(4)); + assertTrue(kernel.supportsModule(5)); + assertTrue(kernel.supportsModule(6)); + ValidationId vId = permissionToIdentifier(permissionId); + ValidationInfo memory vInfo = kernel.validationInfo(vId); + assertTrue(vInfo.hook == address(0)); + assertFalse(kernel.isModuleInstalled(5, address(policy), abi.encodePacked(permissionId))); + assertFalse(kernel.isModuleInstalled(6, address(signer), abi.encodePacked(permissionId))); + vm.expectRevert(NotInstalled.selector); + Install[] memory pkgs = new Install[](2); + pkgs[0] = Install({ + moduleType: 5, + module: address(policy), + moduleData: hex"deadbeef", + internalData: abi.encodePacked(permissionId, hook, kernel.execute.selector) + }); + pkgs[1] = Install({ + moduleType: 6, + module: address(signer), + moduleData: hex"deadbeef", + internalData: abi.encodePacked(permissionId) + }); + kernel.installModule(pkgs); + } + function test_install_policy() external unitTest { assertTrue(kernel.supportsModule(5)); MockPolicy mock = new MockPolicy(); ValidationId vId = permissionToIdentifier(permissionId); - console.log("PermissionId : "); - console.logBytes4(PermissionId.unwrap(permissionId)); ValidationInfo memory vInfo = kernel.validationInfo(vId); - console.log("ValidationId : "); - console.logBytes21(ValidationId.unwrap(vId)); assertTrue(vInfo.hook == address(0)); kernel.installModule(5, address(mock), abi.encode(hex"deadbeef", abi.encodePacked(permissionId))); vInfo = kernel.validationInfo(vId); @@ -175,22 +396,46 @@ abstract contract KernelValidatorTest is KernelTestBase { assertTrue(kernel.isModuleInstalled(6, address(mock), abi.encodePacked(permissionId))); } + function test_install_policy_existing_permission() external unitTest { + Install[] memory pkgs = new Install[](2); + pkgs[0] = Install({ + moduleType: 5, + module: address(policy), + moduleData: hex"deadbeef", + internalData: abi.encodePacked(permissionId, address(0), kernel.execute.selector) + }); + pkgs[1] = Install({ + moduleType: 6, + module: address(signer), + moduleData: hex"deadbeef", + internalData: abi.encodePacked(permissionId) + }); + kernel.installModule(pkgs); + MockPolicy mock = new MockPolicy(); + ValidationId vId = permissionToIdentifier(permissionId); + ValidationInfo memory vInfo = kernel.validationInfo(vId); + assertTrue(vInfo.hook == address(1)); + assertEq(vInfo.policies.length, 1); + assertEq(vInfo.policies[0], address(policy)); + kernel.installModule(5, address(mock), abi.encode(hex"deadbeef", abi.encodePacked(permissionId))); + vInfo = kernel.validationInfo(vId); + assertTrue(vInfo.hook == address(1)); + assertEq(vInfo.policies.length, 2); + assertEq(vInfo.policies[0], address(policy)); + assertEq(vInfo.policies[1], address(mock)); + assertTrue(kernel.isModuleInstalled(5, address(mock), abi.encodePacked(permissionId))); + } + function test_uninstall_signer() external unitTest { MockSigner mock = new MockSigner(); - PermissionId pId = PermissionId.wrap(bytes4(keccak256(abi.encodePacked("deadbeef")))); - //PermissionId pId = PermissionId.wrap(bytes4(hex"deadbeef")); - console.log("PermissionId : "); - console.logBytes4(PermissionId.unwrap(pId)); - ValidationId vId = permissionToIdentifier(pId); - console.log("ValidationId : "); - console.logBytes21(ValidationId.unwrap(vId)); + ValidationId vId = permissionToIdentifier(permissionId); ValidationInfo memory vInfo = kernel.validationInfo(vId); assertTrue(vInfo.hook == address(0)); - kernel.installModule(6, address(mock), abi.encode(hex"deadbeef", abi.encodePacked(pId))); + kernel.installModule(6, address(mock), abi.encode(hex"deadbeef", abi.encodePacked(permissionId))); vInfo = kernel.validationInfo(vId); assertTrue(vInfo.hook == address(1)); assertTrue(vInfo.signer == address(mock)); - kernel.uninstallModule(6, address(mock), abi.encode(hex"deadbeef", abi.encodePacked(pId))); + kernel.uninstallModule(6, address(mock), abi.encode(hex"deadbeef", abi.encodePacked(permissionId))); vInfo = kernel.validationInfo(vId); assertTrue(vInfo.hook == address(0)); assertTrue(vInfo.signer == address(0)); From 59deb907e87d7275e6c0fd6c81bbdc22049c2a32 Mon Sep 17 00:00:00 2001 From: leekt Date: Thu, 16 Oct 2025 01:05:19 +0900 Subject: [PATCH 090/121] make functions payable --- foundry.toml | 2 +- snapshots/KernelFactoryTest.json | 2 +- src/Kernel.sol | 6 +++--- src/KernelUUPS.sol | 2 +- test/KernelTestBase.sol | 2 -- test/mock/MockKernel.sol | 3 +++ 6 files changed, 9 insertions(+), 8 deletions(-) diff --git a/foundry.toml b/foundry.toml index ee0fc192..3bce2541 100644 --- a/foundry.toml +++ b/foundry.toml @@ -6,7 +6,7 @@ via_ir = false # make this true optimizer = true isolate = true -run = 100000 +run = 200000 evm_version = 'prague' solc_version = '0.8.30' diff --git a/snapshots/KernelFactoryTest.json b/snapshots/KernelFactoryTest.json index 6be817d0..34764d6a 100644 --- a/snapshots/KernelFactoryTest.json +++ b/snapshots/KernelFactoryTest.json @@ -1,3 +1,3 @@ { - "Mock - deploy()": "204548" + "Mock - deploy()": "204524" } \ No newline at end of file diff --git a/src/Kernel.sol b/src/Kernel.sol index 3166ed27..c0f45277 100644 --- a/src/Kernel.sol +++ b/src/Kernel.sol @@ -60,7 +60,7 @@ abstract contract Kernel is ModuleManager, ExecutionManager, IERC7579Account { bytes userOpSignature; } - function initialize(Install[] calldata packages) external virtual { + function initialize(Install[] calldata packages) external payable virtual { require(!_initialized(), InvalidInitialization()); // this is initialize // require first package to be the root validator @@ -308,14 +308,14 @@ abstract contract Kernel is ModuleManager, ExecutionManager, IERC7579Account { // NOTE : this ONLY allows root signature, for now function installModule(bool replayable, uint256 nonce, Install[] calldata packages, bytes calldata signature) - external + external payable { // if 7702 or already initialized, use root signature to install module require(_verifyInstallSignature(replayable, nonce, packages, signature), InstallSignatureVerificationFailed()); _install(packages); } - function installModule(Install[] calldata packages) external { + function installModule(Install[] calldata packages) external payable { _onlyEntryPointOrSelf(); _install(packages); } diff --git a/src/KernelUUPS.sol b/src/KernelUUPS.sol index 0f453dd0..f68a80a0 100644 --- a/src/KernelUUPS.sol +++ b/src/KernelUUPS.sol @@ -11,7 +11,7 @@ contract KernelUUPS is Kernel, UUPSUpgradeable, Initializable { _disableInitializers(); } - function initialize(Install[] calldata packages) external override initializer { + function initialize(Install[] calldata packages) external payable override initializer { // this is initialize // require first package to be the root validator _initialize(packages); diff --git a/test/KernelTestBase.sol b/test/KernelTestBase.sol index 7f450c68..4aa1aa75 100644 --- a/test/KernelTestBase.sol +++ b/test/KernelTestBase.sol @@ -15,7 +15,6 @@ import {MockERC721} from "./mock/MockERC721.sol"; import {MockERC1155} from "./mock/MockERC1155.sol"; import {MockCallee} from "./mock/MockCallee.sol"; import {MockContractETH} from "./mock/MockContractETH.sol"; -import {MockKernel} from "./mock/MockKernel.sol"; import {MockHook} from "./mock/MockHook.sol"; import {IValidator} from "src/interfaces/IERC7579Modules.sol"; import {console} from "forge-std/console.sol"; @@ -134,7 +133,6 @@ abstract contract KernelTestBase is Test { function(bytes32, bool) internal returns(bytes memory) signEnable ) internal returns (bytes memory sig) { bytes32 digest = helper.installDigest(address(kernel), replayable, nonce, packages); - MockKernel mockKernel = new MockKernel(ep); if (!is7702) { //vm.store(address(kernel), ERC1967_IMPLEMENTATION_SLOT, bytes32(uint256(uint160(address(mockKernel))))); diff --git a/test/mock/MockKernel.sol b/test/mock/MockKernel.sol index 27f4a1f6..592b0264 100644 --- a/test/mock/MockKernel.sol +++ b/test/mock/MockKernel.sol @@ -2,6 +2,9 @@ pragma solidity ^0.8.0; import {IEntryPoint, Kernel} from "src/Kernel.sol"; import {Call, Install, InstallAndExecute} from "src/types/Structs.sol"; +import { + InvalidInitialization +} from "src/types/Error.sol"; // NOTE: this is not for real usecase, just a contract to deploy for test checks contract MockKernel is Kernel { From 52265ac79231438da417e1b369e3606634260c6c Mon Sep 17 00:00:00 2001 From: leekt Date: Thu, 16 Oct 2025 01:05:52 +0900 Subject: [PATCH 091/121] fmt --- src/Kernel.sol | 6 ++++-- src/core/HookManager.sol | 2 +- src/core/ModuleManager.sol | 4 ++-- src/core/ValidationManager.sol | 1 + test/KernelValidatorTest.sol | 12 ++++++++---- test/mock/MockKernel.sol | 4 +--- 6 files changed, 17 insertions(+), 12 deletions(-) diff --git a/src/Kernel.sol b/src/Kernel.sol index c0f45277..bdf54f95 100644 --- a/src/Kernel.sol +++ b/src/Kernel.sol @@ -36,6 +36,7 @@ import {Received} from "./types/Events.sol"; import {VALIDATION_TYPE_ROOT, VALIDATION_TYPE_PERMISSION, VALIDATION_TYPE_VALIDATOR} from "./types/Constants.sol"; import {ValidationStorage, ValidationInfo} from "./types/Structs.sol"; import "forge-std/console.sol"; + abstract contract Kernel is ModuleManager, ExecutionManager, IERC7579Account { IEntryPoint immutable ENTRYPOINT; @@ -308,13 +309,14 @@ abstract contract Kernel is ModuleManager, ExecutionManager, IERC7579Account { // NOTE : this ONLY allows root signature, for now function installModule(bool replayable, uint256 nonce, Install[] calldata packages, bytes calldata signature) - external payable + external + payable { // if 7702 or already initialized, use root signature to install module require(_verifyInstallSignature(replayable, nonce, packages, signature), InstallSignatureVerificationFailed()); _install(packages); } - + function installModule(Install[] calldata packages) external payable { _onlyEntryPointOrSelf(); _install(packages); diff --git a/src/core/HookManager.sol b/src/core/HookManager.sol index cc727674..6ef663f7 100644 --- a/src/core/HookManager.sol +++ b/src/core/HookManager.sol @@ -8,7 +8,7 @@ abstract contract HookManager { struct HookStorage { mapping(address => bool) enabled; } - + function _hookEnabled(IHook _hook) internal view virtual returns (bool) { return _hookStorage().enabled[address(_hook)]; } diff --git a/src/core/ModuleManager.sol b/src/core/ModuleManager.sol index f8af81f0..9d03d14c 100644 --- a/src/core/ModuleManager.sol +++ b/src/core/ModuleManager.sol @@ -55,7 +55,7 @@ abstract contract ModuleManager is ValidationManager, ExecutorManager, HookManag } return (uint256(key) << 64) + seq; } - + function _hookEnabled(IHook _hook) internal view override(ValidationManager, HookManager) returns (bool) { return HookManager._hookEnabled(_hook); } @@ -176,7 +176,7 @@ abstract contract ModuleManager is ValidationManager, ExecutorManager, HookManag _installModule(pkg.moduleType, pkg.module, pkg.moduleData, pkg.internalData); } } - + require( ValidationId.unwrap(installingPermission) == bytes21(0) || _validationStorage().vInfo[installingPermission].signer != address(0), diff --git a/src/core/ValidationManager.sol b/src/core/ValidationManager.sol index 892b064f..d92c7d0a 100644 --- a/src/core/ValidationManager.sol +++ b/src/core/ValidationManager.sol @@ -36,6 +36,7 @@ function parseNonce(uint256 nonce) pure returns (ValidationMode vMode, Validatio abstract contract ValidationManager { error InvalidVid(ValidationId vId); + ValidationId transient installingPermission; function _hookEnabled(IHook _hook) internal view virtual returns (bool); diff --git a/test/KernelValidatorTest.sol b/test/KernelValidatorTest.sol index e625e293..2bee8a88 100644 --- a/test/KernelValidatorTest.sol +++ b/test/KernelValidatorTest.sol @@ -181,7 +181,8 @@ abstract contract KernelValidatorTest is KernelTestBase { ValidationInfo memory vInfo = kernel.validationInfo(vId); assertTrue(vInfo.hook == address(0)); bytes4 ret = kernel.isValidSignature( - keccak256("Hello world"), abi.encodePacked(bytes1(0x01), newValidator, _validatorSignHash(keccak256("Hello world"), true)) + keccak256("Hello world"), + abi.encodePacked(bytes1(0x01), newValidator, _validatorSignHash(keccak256("Hello world"), true)) ); assertEq(ret, ERC1271_MAGICVALUE); assertTrue(kernel.isModuleInstalled(1, address(newValidator), hex"")); @@ -196,7 +197,8 @@ abstract contract KernelValidatorTest is KernelTestBase { ValidationInfo memory vInfo = kernel.validationInfo(vId); assertTrue(vInfo.hook == address(0)); bytes4 ret = kernel.isValidSignature( - keccak256("Hello world"), abi.encodePacked(bytes1(0x01), newValidator, _validatorSignHash(keccak256("Hello world"), true)) + keccak256("Hello world"), + abi.encodePacked(bytes1(0x01), newValidator, _validatorSignHash(keccak256("Hello world"), true)) ); assertEq(ret, ERC1271_MAGICVALUE); assertTrue(kernel.isModuleInstalled(1, address(newValidator), hex"")); @@ -213,7 +215,8 @@ abstract contract KernelValidatorTest is KernelTestBase { ValidationInfo memory vInfo = kernel.validationInfo(vId); assertTrue(vInfo.hook == address(0)); bytes4 ret = kernel.isValidSignature( - keccak256("Hello world"), abi.encodePacked(bytes1(0x01), newValidator, _validatorSignHash(keccak256("Hello world"), true)) + keccak256("Hello world"), + abi.encodePacked(bytes1(0x01), newValidator, _validatorSignHash(keccak256("Hello world"), true)) ); assertEq(ret, ERC1271_MAGICVALUE); assertTrue(kernel.isModuleInstalled(1, address(newValidator), hex"")); @@ -234,7 +237,8 @@ abstract contract KernelValidatorTest is KernelTestBase { ValidationInfo memory vInfo = kernel.validationInfo(vId); assertTrue(vInfo.hook == address(0)); bytes4 ret = kernel.isValidSignature( - keccak256("Hello world"), abi.encodePacked(bytes1(0x01), newValidator, _validatorSignHash(keccak256("Hello world"), true)) + keccak256("Hello world"), + abi.encodePacked(bytes1(0x01), newValidator, _validatorSignHash(keccak256("Hello world"), true)) ); assertEq(ret, ERC1271_MAGICVALUE); assertTrue(kernel.isModuleInstalled(1, address(newValidator), hex"")); diff --git a/test/mock/MockKernel.sol b/test/mock/MockKernel.sol index 592b0264..b8d07f7e 100644 --- a/test/mock/MockKernel.sol +++ b/test/mock/MockKernel.sol @@ -2,9 +2,7 @@ pragma solidity ^0.8.0; import {IEntryPoint, Kernel} from "src/Kernel.sol"; import {Call, Install, InstallAndExecute} from "src/types/Structs.sol"; -import { - InvalidInitialization -} from "src/types/Error.sol"; +import {InvalidInitialization} from "src/types/Error.sol"; // NOTE: this is not for real usecase, just a contract to deploy for test checks contract MockKernel is Kernel { From e4431dbb0b127b6914cc117e8687d3f0382c43b3 Mon Sep 17 00:00:00 2001 From: leekt Date: Thu, 16 Oct 2025 01:27:13 +0900 Subject: [PATCH 092/121] feat: staker --- src/Staker.sol | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 src/Staker.sol diff --git a/src/Staker.sol b/src/Staker.sol new file mode 100644 index 00000000..017ca3f8 --- /dev/null +++ b/src/Staker.sol @@ -0,0 +1,67 @@ +pragma solidity ^0.8.0; + +import {IEntryPoint} from "account-abstraction/interfaces/IEntryPoint.sol"; +import {Ownable} from "solady/auth/Ownable.sol"; +import {EIP712} from "solady/utils/EIP712.sol"; +import {ECDSA} from "solady/utils/ECDSA.sol"; + +contract Staker is Ownable, EIP712 { + mapping(address => bool) public approved; + + error NotApprovedFactory(); + + constructor(address _owner) { + _initializeOwner(_owner); + } + + function _domainNameAndVersion() internal view override returns(string memory, string memory) { + return ("Staker", "0.0.1"); + } + + function deployWithFactory(address factory, bytes calldata createData) + external + payable + returns (address) + { + if (!approved[factory]) { + revert NotApprovedFactory(); + } + (bool success, bytes memory ret) = factory.call(createData); + return abi.decode(ret, (address)); + } + + function approveFactory(address _factory, bool approval) external payable onlyOwner { + approved[_factory] = approval; + } + + function approveFactoryWithSignature(address _factory, bool approval, bytes calldata signature) external payable onlyOwner { + // struct : + // { + // factory: address, + // approval: bool, + // } + bytes32 digest = _hashTypedDataSansChainId( + keccak256( + abi.encode( + keccak256("ApproveFactory(address factory,bool approval)"), + _factory, + approval + ) + ) + ); + require(owner() == ECDSA.recover(digest, signature), "InvalidSignature"); + approved[_factory] = approval; + } + + function stake(IEntryPoint entryPoint, uint32 unstakeDelay) external payable onlyOwner { + entryPoint.addStake{value: msg.value}(unstakeDelay); + } + + function unlockStake(IEntryPoint entryPoint) external payable onlyOwner { + entryPoint.unlockStake(); + } + + function withdrawStake(IEntryPoint entryPoint, address payable recipient) external payable onlyOwner { + entryPoint.withdrawStake(recipient); + } +} From 6e3273d46875704e8e8b8a96903e10a3464adbb2 Mon Sep 17 00:00:00 2001 From: leekt Date: Thu, 16 Oct 2025 10:25:04 +0900 Subject: [PATCH 093/121] added simple account comparison data --- .gitmodules | 3 +++ foundry.lock | 15 +++++++++--- lib/openzeppelin-contracts | 1 + remappings.txt | 7 ++++++ snapshots/Kernel7702Test.json | 3 ++- snapshots/KernelECDSATest.json | 3 ++- snapshots/KernelImmutableECDSATest.json | 3 ++- snapshots/KernelTest.json | 3 ++- test/KernelUserOpTest.sol | 32 +++++++++++++++++++++++++ 9 files changed, 63 insertions(+), 7 deletions(-) create mode 160000 lib/openzeppelin-contracts create mode 100644 remappings.txt diff --git a/.gitmodules b/.gitmodules index a65a2247..7c0dce29 100644 --- a/.gitmodules +++ b/.gitmodules @@ -11,3 +11,6 @@ [submodule "lib/halmos-cheatcodes"] path = lib/halmos-cheatcodes url = https://github.com/a16z/halmos-cheatcodes +[submodule "lib/openzeppelin-contracts"] + path = lib/openzeppelin-contracts + url = https://github.com/openzeppelin/openzeppelin-contracts diff --git a/foundry.lock b/foundry.lock index 2a76b545..081a0733 100644 --- a/foundry.lock +++ b/foundry.lock @@ -1,7 +1,4 @@ { - "lib/solady": { - "rev": "b609a9c79ce541c2beca7a7d247665e7c93942a3" - }, "lib/account-abstraction": { "branch": { "name": "develop", @@ -10,5 +7,17 @@ }, "lib/forge-std": { "rev": "f46d8301cf732f4f83846565aa475628265e51e0" + }, + "lib/halmos-cheatcodes": { + "rev": "6da4e692c357ba6d641a2e677a28298cac9f76ab" + }, + "lib/openzeppelin-contracts": { + "tag": { + "name": "v5.4.0", + "rev": "c64a1edb67b6e3f4a15cca8909c9482ad33a02b0" + } + }, + "lib/solady": { + "rev": "b609a9c79ce541c2beca7a7d247665e7c93942a3" } } \ No newline at end of file diff --git a/lib/openzeppelin-contracts b/lib/openzeppelin-contracts new file mode 160000 index 00000000..c64a1edb --- /dev/null +++ b/lib/openzeppelin-contracts @@ -0,0 +1 @@ +Subproject commit c64a1edb67b6e3f4a15cca8909c9482ad33a02b0 diff --git a/remappings.txt b/remappings.txt new file mode 100644 index 00000000..adbdb911 --- /dev/null +++ b/remappings.txt @@ -0,0 +1,7 @@ +@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/ +account-abstraction/=lib/account-abstraction/contracts/ +erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/ +forge-std/=lib/forge-std/src/ +halmos-cheatcodes/=lib/halmos-cheatcodes/src/ +openzeppelin-contracts/=lib/openzeppelin-contracts/ +solady/=lib/solady/src/ diff --git a/snapshots/Kernel7702Test.json b/snapshots/Kernel7702Test.json index 1c8d5539..f4058c33 100644 --- a/snapshots/Kernel7702Test.json +++ b/snapshots/Kernel7702Test.json @@ -1,3 +1,4 @@ { - "Root - foo()": "179326" + "Root - foo()": "179326", + "Simple - foo()": "176652" } \ No newline at end of file diff --git a/snapshots/KernelECDSATest.json b/snapshots/KernelECDSATest.json index b75e6d46..480ffe15 100644 --- a/snapshots/KernelECDSATest.json +++ b/snapshots/KernelECDSATest.json @@ -1,3 +1,4 @@ { - "Root - foo()": "191085" + "Root - foo()": "191085", + "Simple - foo()": "176652" } \ No newline at end of file diff --git a/snapshots/KernelImmutableECDSATest.json b/snapshots/KernelImmutableECDSATest.json index 2b9054fd..72a54115 100644 --- a/snapshots/KernelImmutableECDSATest.json +++ b/snapshots/KernelImmutableECDSATest.json @@ -1,3 +1,4 @@ { - "Root - foo()": "182341" + "Root - foo()": "182341", + "Simple - foo()": "176652" } \ No newline at end of file diff --git a/snapshots/KernelTest.json b/snapshots/KernelTest.json index 7f0aa5ea..bd655a2d 100644 --- a/snapshots/KernelTest.json +++ b/snapshots/KernelTest.json @@ -1,3 +1,4 @@ { - "Root - foo()": "208275" + "Root - foo()": "208275", + "Simple - foo()": "176652" } \ No newline at end of file diff --git a/test/KernelUserOpTest.sol b/test/KernelUserOpTest.sol index 0f55398a..ef9d84f4 100644 --- a/test/KernelUserOpTest.sol +++ b/test/KernelUserOpTest.sol @@ -7,6 +7,8 @@ import {MockCallee} from "./mock/MockCallee.sol"; import {KernelTestBase} from "./KernelTestBase.sol"; import {PermissionId} from "src/types/Types.sol"; import {validatorToIdentifier} from "src/lib/Utils.sol"; +import {SimpleAccount} from "account-abstraction/accounts/SimpleAccount.sol"; +import {SimpleAccountFactory} from "account-abstraction/accounts/SimpleAccountFactory.sol"; abstract contract KernelUserOpTest is KernelTestBase { function test_executeuserop_root() external entryPointTest { @@ -36,6 +38,36 @@ abstract contract KernelUserOpTest is KernelTestBase { assertEq(callee.bar(), 1); } + function test_userop_simple_account_compare() external entryPointTest { + (address simpleOwner, uint256 simpleKey) = makeAddrAndKey("SimpleOwner"); + SimpleAccountFactory factory = new SimpleAccountFactory(ep); + vm.startPrank(address(ep.senderCreator())); + SimpleAccount account = factory.createAccount(simpleOwner, 0); + vm.stopPrank(); + vm.deal(address(account), 1e18); + PackedUserOperation[] memory ops = new PackedUserOperation[](1); + ops[0] = PackedUserOperation({ + sender: address(account), + nonce: 0, + initCode: hex"", + callData: abi.encodeWithSelector( + account.execute.selector, address(callee), uint256(0), abi.encodePacked(MockCallee.foo.selector) + ), + accountGasLimits: bytes32(abi.encodePacked(uint128(1000000), uint128(1000000))), + preVerificationGas: 1000000, + gasFees: bytes32(abi.encodePacked(uint128(1), uint128(1))), + paymasterAndData: hex"", + signature: hex"" + }); + bytes32 userOpHash = ep.getUserOpHash(ops[0]); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(simpleKey, userOpHash); + ops[0].signature = abi.encodePacked(r,s,v); + vm.startSnapshotGas("Simple - foo()"); + ep.handleOps(ops, beneficiary); + vm.stopSnapshotGas(); + assertEq(callee.bar(), 1); + } + function test_userop_root() external entryPointTest { PackedUserOperation[] memory ops = new PackedUserOperation[](1); ops[0] = PackedUserOperation({ From cdf738bce9630b216392f2a8183f63b2849965c8 Mon Sep 17 00:00:00 2001 From: leekt Date: Fri, 17 Oct 2025 14:48:07 +0900 Subject: [PATCH 094/121] feat: hook use check --- .gitmodules | 13 - .../@openzeppelin-contracts-5.4.0/README.md | 108 + .../access/AccessControl.sol | 207 + .../access/IAccessControl.sol | 98 + .../access/Ownable.sol | 100 + .../access/Ownable2Step.sol | 67 + .../AccessControlDefaultAdminRules.sol | 372 + .../extensions/AccessControlEnumerable.sol | 81 + .../IAccessControlDefaultAdminRules.sol | 192 + .../extensions/IAccessControlEnumerable.sol | 31 + .../access/manager/AccessManaged.sol | 112 + .../access/manager/AccessManager.sol | 740 ++ .../access/manager/AuthorityUtils.sol | 36 + .../access/manager/IAccessManaged.sol | 32 + .../access/manager/IAccessManager.sol | 399 + .../access/manager/IAuthority.sol | 14 + .../account/Account.sol | 145 + .../extensions/draft-AccountERC7579.sol | 405 + .../extensions/draft-AccountERC7579Hooked.sol | 107 + .../account/extensions/draft-ERC7821.sol | 70 + .../account/utils/EIP7702Utils.sol | 21 + .../account/utils/draft-ERC4337Utils.sol | 159 + .../account/utils/draft-ERC7579Utils.sol | 280 + .../build/contracts/AbstractSigner.json | 10 + .../build/contracts/AccessControl.json | 236 + .../AccessControlDefaultAdminRules.json | 464 + .../contracts/AccessControlEnumerable.json | 298 + .../build/contracts/AccessManaged.json | 101 + .../build/contracts/AccessManager.json | 1175 ++ .../build/contracts/Account.json | 147 + .../build/contracts/AccountERC7579.json | 507 + .../build/contracts/AccountERC7579Hooked.json | 531 + .../build/contracts/Address.json | 22 + .../build/contracts/Arrays.json | 10 + .../build/contracts/AuthorityUtils.json | 10 + .../build/contracts/Base64.json | 10 + .../build/contracts/BeaconProxy.json | 87 + .../build/contracts/BitMaps.json | 10 + .../build/contracts/Blockhash.json | 10 + .../build/contracts/Bytes.json | 10 + .../build/contracts/CAIP10.json | 10 + .../build/contracts/CAIP2.json | 10 + .../build/contracts/Calldata.json | 10 + .../build/contracts/Checkpoints.json | 16 + .../build/contracts/CircularBuffer.json | 16 + .../build/contracts/Clones.json | 16 + .../build/contracts/Comparators.json | 10 + .../build/contracts/Context.json | 10 + .../build/contracts/Create2.json | 16 + .../build/contracts/DoubleEndedQueue.json | 10 + .../build/contracts/ECDSA.json | 38 + .../build/contracts/EIP712.json | 76 + .../build/contracts/EIP7702Utils.json | 10 + .../build/contracts/ERC1155.json | 425 + .../build/contracts/ERC1155Burnable.json | 471 + .../build/contracts/ERC1155Holder.json | 108 + .../build/contracts/ERC1155Pausable.json | 474 + .../build/contracts/ERC1155Supply.json | 476 + .../build/contracts/ERC1155URIStorage.json | 425 + .../build/contracts/ERC1155Utils.json | 10 + .../build/contracts/ERC1363.json | 582 + .../build/contracts/ERC1363Utils.json | 33 + .../build/contracts/ERC165.json | 30 + .../build/contracts/ERC165Checker.json | 10 + .../build/contracts/ERC1967Proxy.json | 76 + .../build/contracts/ERC1967Utils.json | 49 + .../build/contracts/ERC20.json | 319 + .../build/contracts/ERC20Bridgeable.json | 424 + .../build/contracts/ERC20Burnable.json | 350 + .../build/contracts/ERC20Capped.json | 359 + .../build/contracts/ERC20FlashMint.json | 429 + .../build/contracts/ERC20Pausable.json | 368 + .../build/contracts/ERC20Permit.json | 529 + .../contracts/ERC20TemporaryApproval.json | 343 + .../build/contracts/ERC20Votes.json | 778 ++ .../build/contracts/ERC20Wrapper.json | 402 + .../build/contracts/ERC2771Context.json | 43 + .../build/contracts/ERC2771Forwarder.json | 388 + .../build/contracts/ERC2981.json | 123 + .../build/contracts/ERC4337Utils.json | 10 + .../build/contracts/ERC4626.json | 804 ++ .../build/contracts/ERC6909.json | 412 + .../build/contracts/ERC6909ContentURI.json | 469 + .../build/contracts/ERC6909Metadata.json | 526 + .../build/contracts/ERC6909TokenSupply.json | 431 + .../build/contracts/ERC721.json | 444 + .../build/contracts/ERC721Burnable.json | 457 + .../build/contracts/ERC721Consecutive.json | 506 + .../build/contracts/ERC721Enumerable.json | 521 + .../build/contracts/ERC721Holder.json | 45 + .../build/contracts/ERC721Pausable.json | 493 + .../build/contracts/ERC721Royalty.json | 537 + .../build/contracts/ERC721URIStorage.json | 476 + .../build/contracts/ERC721Utils.json | 10 + .../build/contracts/ERC721Votes.json | 832 ++ .../build/contracts/ERC721Wrapper.json | 550 + .../build/contracts/ERC7579Utils.json | 116 + .../build/contracts/ERC7739.json | 100 + .../build/contracts/ERC7739Utils.json | 10 + .../build/contracts/ERC7821.json | 109 + .../build/contracts/ERC7913P256Verifier.json | 40 + .../build/contracts/ERC7913RSAVerifier.json | 40 + .../build/contracts/EnumerableMap.json | 33 + .../build/contracts/EnumerableSet.json | 10 + .../build/contracts/Errors.json | 48 + .../build/contracts/Governor.json | 1372 ++ .../contracts/GovernorCountingFractional.json | 1446 +++ .../GovernorCountingOverridable.json | 1598 +++ .../contracts/GovernorCountingSimple.json | 1401 +++ .../build/contracts/GovernorNoncesKeyed.json | 1396 +++ .../contracts/GovernorPreventLateQuorum.json | 1436 +++ .../contracts/GovernorProposalGuardian.json | 1417 +++ .../GovernorSequentialProposalId.json | 1390 +++ .../build/contracts/GovernorSettings.json | 1468 +++ .../build/contracts/GovernorStorage.json | 1497 +++ .../build/contracts/GovernorSuperQuorum.json | 1420 +++ .../contracts/GovernorTimelockAccess.json | 1573 +++ .../contracts/GovernorTimelockCompound.json | 1440 +++ .../contracts/GovernorTimelockControl.json | 1417 +++ .../build/contracts/GovernorVotes.json | 1385 +++ .../GovernorVotesQuorumFraction.json | 1483 +++ .../GovernorVotesSuperQuorumFraction.json | 1643 +++ .../build/contracts/Hashes.json | 10 + .../build/contracts/Heap.json | 10 + .../build/contracts/IAccessControl.json | 204 + .../IAccessControlDefaultAdminRules.json | 403 + .../contracts/IAccessControlEnumerable.json | 247 + .../build/contracts/IAccessManaged.json | 101 + .../build/contracts/IAccessManager.json | 1071 ++ .../build/contracts/IAccount.json | 87 + .../build/contracts/IAccountExecute.json | 76 + .../build/contracts/IAggregator.json | 208 + .../build/contracts/IAuthority.json | 40 + .../build/contracts/IBeacon.json | 24 + .../build/contracts/ICompoundTimelock.json | 424 + .../build/contracts/IERC1155.json | 304 + .../build/contracts/IERC1155Errors.json | 113 + .../build/contracts/IERC1155MetadataURI.json | 323 + .../build/contracts/IERC1155Receiver.json | 108 + .../build/contracts/IERC1271.json | 35 + .../build/contracts/IERC1363.json | 382 + .../build/contracts/IERC1363Receiver.json | 45 + .../build/contracts/IERC1363Spender.json | 40 + .../build/contracts/IERC165.json | 30 + .../build/contracts/IERC1820Implementer.json | 35 + .../build/contracts/IERC1820Registry.json | 224 + .../build/contracts/IERC1822Proxiable.json | 24 + .../build/contracts/IERC1967.json | 56 + .../build/contracts/IERC20.json | 194 + .../build/contracts/IERC20Errors.json | 97 + .../build/contracts/IERC20Metadata.json | 233 + .../build/contracts/IERC20Permit.json | 86 + .../build/contracts/IERC2309.json | 42 + .../build/contracts/IERC2612.json | 86 + .../build/contracts/IERC2981.json | 59 + .../contracts/IERC3156FlashBorrower.json | 50 + .../build/contracts/IERC3156FlashLender.json | 88 + .../build/contracts/IERC4626.json | 623 + .../build/contracts/IERC4906.json | 328 + .../build/contracts/IERC5267.json | 60 + .../build/contracts/IERC5313.json | 24 + .../build/contracts/IERC5805.json | 230 + .../build/contracts/IERC6372.json | 37 + .../build/contracts/IERC6909.json | 316 + .../build/contracts/IERC6909ContentURI.json | 348 + .../build/contracts/IERC6909Metadata.json | 373 + .../build/contracts/IERC6909TokenSupply.json | 335 + .../build/contracts/IERC721.json | 296 + .../build/contracts/IERC721Enumerable.json | 352 + .../build/contracts/IERC721Errors.json | 114 + .../build/contracts/IERC721Metadata.json | 341 + .../build/contracts/IERC721Receiver.json | 45 + .../contracts/IERC7579AccountConfig.json | 62 + .../build/contracts/IERC7579Execution.json | 53 + .../build/contracts/IERC7579Hook.json | 98 + .../build/contracts/IERC7579Module.json | 56 + .../build/contracts/IERC7579ModuleConfig.json | 124 + .../build/contracts/IERC7579Validator.json | 156 + .../build/contracts/IERC7674.json | 218 + .../build/contracts/IERC777.json | 402 + .../build/contracts/IERC777Recipient.json | 49 + .../build/contracts/IERC777Sender.json | 49 + .../build/contracts/IERC7802.json | 116 + .../build/contracts/IERC7821.json | 48 + .../contracts/IERC7913SignatureVerifier.json | 40 + .../build/contracts/IEntryPoint.json | 302 + .../build/contracts/IEntryPointExtra.json | 77 + .../build/contracts/IEntryPointNonces.json | 35 + .../build/contracts/IEntryPointStake.json | 94 + .../build/contracts/IGovernor.json | 1086 ++ .../build/contracts/IPaymaster.json | 120 + .../ITransparentUpgradeableProxy.json | 74 + .../build/contracts/IVotes.json | 204 + .../build/contracts/Initializable.json | 34 + .../build/contracts/Math.json | 10 + .../build/contracts/MerkleProof.json | 16 + .../build/contracts/MerkleTree.json | 32 + .../build/contracts/MessageHashUtils.json | 10 + .../build/contracts/MultiSignerERC7913.json | 173 + .../contracts/MultiSignerERC7913Weighted.json | 261 + .../build/contracts/Multicall.json | 46 + .../build/contracts/Nonces.json | 46 + .../build/contracts/NoncesKeyed.json | 70 + .../build/contracts/Ownable.json | 85 + .../build/contracts/Ownable2Step.json | 124 + .../build/contracts/P256.json | 10 + .../build/contracts/Packing.json | 16 + .../build/contracts/Panic.json | 10 + .../build/contracts/Pausable.json | 60 + .../build/contracts/Proxy.json | 15 + .../build/contracts/ProxyAdmin.json | 132 + .../build/contracts/RSA.json | 10 + .../build/contracts/ReentrancyGuard.json | 16 + .../contracts/ReentrancyGuardTransient.json | 16 + .../build/contracts/SafeCast.json | 65 + .../build/contracts/SafeERC20.json | 43 + .../build/contracts/ShortStrings.json | 27 + .../build/contracts/SignatureChecker.json | 10 + .../build/contracts/SignedMath.json | 10 + .../build/contracts/SignerECDSA.json | 24 + .../build/contracts/SignerERC7702.json | 10 + .../build/contracts/SignerERC7913.json | 24 + .../build/contracts/SignerP256.json | 45 + .../build/contracts/SignerRSA.json | 29 + .../build/contracts/SlotDerivation.json | 10 + .../build/contracts/StorageSlot.json | 10 + .../build/contracts/Strings.json | 37 + .../build/contracts/Time.json | 10 + .../build/contracts/TimelockController.json | 1007 ++ .../build/contracts/TransientSlot.json | 10 + .../TransparentUpgradeableProxy.json | 116 + .../build/contracts/UUPSUpgradeable.json | 116 + .../build/contracts/UpgradeableBeacon.json | 151 + .../build/contracts/VestingWallet.json | 340 + .../build/contracts/VestingWalletCliff.json | 364 + .../build/contracts/Votes.json | 399 + .../build/contracts/VotesExtended.json | 447 + .../finance/VestingWallet.sol | 159 + .../finance/VestingWalletCliff.sol | 54 + .../governance/Governor.sol | 818 ++ .../governance/IGovernor.sol | 454 + .../governance/TimelockController.sol | 471 + .../extensions/GovernorCountingFractional.sol | 190 + .../GovernorCountingOverridable.sol | 222 + .../extensions/GovernorCountingSimple.sol | 96 + .../extensions/GovernorNoncesKeyed.sol | 91 + .../extensions/GovernorPreventLateQuorum.sol | 92 + .../extensions/GovernorProposalGuardian.sol | 58 + .../GovernorSequentialProposalId.sol | 75 + .../extensions/GovernorSettings.sol | 106 + .../governance/extensions/GovernorStorage.sol | 125 + .../extensions/GovernorSuperQuorum.sol | 58 + .../extensions/GovernorTimelockAccess.sol | 346 + .../extensions/GovernorTimelockCompound.sol | 165 + .../extensions/GovernorTimelockControl.sol | 167 + .../governance/extensions/GovernorVotes.sol | 63 + .../GovernorVotesQuorumFraction.sol | 113 + .../GovernorVotesSuperQuorumFraction.sol | 134 + .../governance/utils/IVotes.sol | 59 + .../governance/utils/Votes.sol | 252 + .../governance/utils/VotesExtended.sol | 84 + .../interfaces/IERC1155.sol | 6 + .../interfaces/IERC1155MetadataURI.sol | 6 + .../interfaces/IERC1155Receiver.sol | 6 + .../interfaces/IERC1271.sol | 17 + .../interfaces/IERC1363.sol | 86 + .../interfaces/IERC1363Receiver.sol | 32 + .../interfaces/IERC1363Spender.sol | 26 + .../interfaces/IERC165.sol | 6 + .../interfaces/IERC1820Implementer.sol | 20 + .../interfaces/IERC1820Registry.sol | 112 + .../interfaces/IERC1967.sol | 24 + .../interfaces/IERC20.sol | 6 + .../interfaces/IERC20Metadata.sol | 6 + .../interfaces/IERC2309.sol | 19 + .../interfaces/IERC2612.sol | 8 + .../interfaces/IERC2981.sol | 26 + .../interfaces/IERC3156.sol | 7 + .../interfaces/IERC3156FlashBorrower.sol | 27 + .../interfaces/IERC3156FlashLender.sol | 41 + .../interfaces/IERC4626.sol | 230 + .../interfaces/IERC4906.sol | 20 + .../interfaces/IERC5267.sol | 28 + .../interfaces/IERC5313.sol | 16 + .../interfaces/IERC5805.sol | 9 + .../interfaces/IERC6372.sol | 17 + .../interfaces/IERC721.sol | 6 + .../interfaces/IERC721Enumerable.sol | 6 + .../interfaces/IERC721Metadata.sol | 6 + .../interfaces/IERC721Receiver.sol | 6 + .../interfaces/IERC777.sol | 200 + .../interfaces/IERC777Recipient.sol | 35 + .../interfaces/IERC777Sender.sol | 35 + .../interfaces/IERC7913.sol | 18 + .../interfaces/draft-IERC1822.sol | 20 + .../interfaces/draft-IERC4337.sol | 253 + .../interfaces/draft-IERC6093.sol | 161 + .../interfaces/draft-IERC6909.sol | 125 + .../interfaces/draft-IERC7579.sol | 226 + .../interfaces/draft-IERC7674.sol | 17 + .../interfaces/draft-IERC7802.sol | 31 + .../interfaces/draft-IERC7821.sol | 44 + .../metatx/ERC2771Context.sol | 90 + .../metatx/ERC2771Forwarder.sol | 372 + .../proxy/Clones.sol | 294 + .../proxy/ERC1967/ERC1967Proxy.sol | 40 + .../proxy/ERC1967/ERC1967Utils.sol | 177 + .../proxy/Proxy.sol | 69 + .../proxy/beacon/BeaconProxy.sol | 57 + .../proxy/beacon/IBeacon.sol | 16 + .../proxy/beacon/UpgradeableBeacon.sol | 70 + .../proxy/transparent/ProxyAdmin.sol | 45 + .../TransparentUpgradeableProxy.sol | 118 + .../proxy/utils/Initializable.sol | 238 + .../proxy/utils/UUPSUpgradeable.sol | 146 + .../token/ERC1155/ERC1155.sol | 389 + .../token/ERC1155/IERC1155.sol | 123 + .../token/ERC1155/IERC1155Receiver.sol | 59 + .../ERC1155/extensions/ERC1155Burnable.sol | 28 + .../ERC1155/extensions/ERC1155Pausable.sol | 38 + .../ERC1155/extensions/ERC1155Supply.sol | 88 + .../ERC1155/extensions/ERC1155URIStorage.sol | 61 + .../extensions/IERC1155MetadataURI.sol | 20 + .../token/ERC1155/utils/ERC1155Holder.sol | 40 + .../token/ERC1155/utils/ERC1155Utils.sol | 88 + .../token/ERC20/ERC20.sol | 305 + .../token/ERC20/IERC20.sol | 79 + .../token/ERC20/extensions/ERC1363.sol | 135 + .../token/ERC20/extensions/ERC20Burnable.sol | 39 + .../token/ERC20/extensions/ERC20Capped.sol | 54 + .../token/ERC20/extensions/ERC20FlashMint.sol | 134 + .../token/ERC20/extensions/ERC20Pausable.sol | 33 + .../token/ERC20/extensions/ERC20Permit.sol | 77 + .../token/ERC20/extensions/ERC20Votes.sol | 83 + .../token/ERC20/extensions/ERC20Wrapper.sol | 89 + .../token/ERC20/extensions/ERC4626.sol | 282 + .../token/ERC20/extensions/IERC20Metadata.sol | 26 + .../token/ERC20/extensions/IERC20Permit.sol | 90 + .../extensions/draft-ERC20Bridgeable.sol | 51 + .../draft-ERC20TemporaryApproval.sol | 119 + .../token/ERC20/utils/ERC1363Utils.sol | 95 + .../token/ERC20/utils/SafeERC20.sol | 212 + .../token/ERC6909/draft-ERC6909.sol | 224 + .../extensions/draft-ERC6909ContentURI.sol | 53 + .../extensions/draft-ERC6909Metadata.sol | 77 + .../extensions/draft-ERC6909TokenSupply.sol | 35 + .../token/ERC721/ERC721.sol | 430 + .../token/ERC721/IERC721.sol | 135 + .../token/ERC721/IERC721Receiver.sol | 28 + .../ERC721/extensions/ERC721Burnable.sol | 26 + .../ERC721/extensions/ERC721Consecutive.sol | 176 + .../ERC721/extensions/ERC721Enumerable.sol | 164 + .../ERC721/extensions/ERC721Pausable.sol | 37 + .../token/ERC721/extensions/ERC721Royalty.sol | 26 + .../ERC721/extensions/ERC721URIStorage.sol | 58 + .../token/ERC721/extensions/ERC721Votes.sol | 47 + .../token/ERC721/extensions/ERC721Wrapper.sol | 102 + .../ERC721/extensions/IERC721Enumerable.sol | 29 + .../ERC721/extensions/IERC721Metadata.sol | 27 + .../token/ERC721/utils/ERC721Holder.sol | 24 + .../token/ERC721/utils/ERC721Utils.sol | 50 + .../token/common/ERC2981.sol | 139 + .../utils/Address.sol | 149 + .../utils/Arrays.sol | 552 + .../utils/Base64.sol | 119 + .../utils/Blockhash.sol | 53 + .../utils/Bytes.sol | 113 + .../utils/CAIP10.sol | 54 + .../utils/CAIP2.sol | 51 + .../utils/Calldata.sol | 25 + .../utils/Comparators.sol | 19 + .../utils/Context.sol | 28 + .../utils/Create2.sol | 92 + .../utils/Errors.sol | 34 + .../utils/Multicall.sol | 37 + .../utils/Nonces.sol | 46 + .../utils/NoncesKeyed.sol | 74 + .../utils/Packing.sol | 1656 +++ .../utils/Panic.sol | 57 + .../utils/Pausable.sol | 112 + .../utils/ReentrancyGuard.sol | 87 + .../utils/ReentrancyGuardTransient.sol | 61 + .../utils/ShortStrings.sol | 122 + .../utils/SlotDerivation.sol | 155 + .../utils/StorageSlot.sol | 143 + .../utils/Strings.sol | 490 + .../utils/TransientSlot.sol | 183 + .../utils/cryptography/ECDSA.sol | 180 + .../utils/cryptography/EIP712.sol | 160 + .../utils/cryptography/Hashes.sol | 31 + .../utils/cryptography/MerkleProof.sol | 514 + .../utils/cryptography/MessageHashUtils.sol | 99 + .../utils/cryptography/P256.sol | 408 + .../utils/cryptography/RSA.sol | 154 + .../utils/cryptography/SignatureChecker.sol | 135 + .../utils/cryptography/draft-ERC7739Utils.sol | 207 + .../cryptography/signers/AbstractSigner.sol | 23 + .../signers/MultiSignerERC7913.sol | 252 + .../signers/MultiSignerERC7913Weighted.sol | 208 + .../cryptography/signers/SignerECDSA.sol | 56 + .../cryptography/signers/SignerERC7702.sol | 25 + .../cryptography/signers/SignerERC7913.sol | 63 + .../utils/cryptography/signers/SignerP256.sol | 64 + .../utils/cryptography/signers/SignerRSA.sol | 65 + .../cryptography/signers/draft-ERC7739.sol | 99 + .../verifiers/ERC7913P256Verifier.sol | 29 + .../verifiers/ERC7913RSAVerifier.sol | 23 + .../utils/introspection/ERC165.sol | 25 + .../utils/introspection/ERC165Checker.sol | 124 + .../utils/introspection/IERC165.sol | 25 + .../utils/math/Math.sol | 749 ++ .../utils/math/SafeCast.sol | 1162 ++ .../utils/math/SignedMath.sol | 68 + .../utils/structs/BitMaps.sol | 60 + .../utils/structs/Checkpoints.sol | 630 + .../utils/structs/CircularBuffer.sol | 140 + .../utils/structs/DoubleEndedQueue.sol | 156 + .../utils/structs/EnumerableMap.sol | 1319 ++ .../utils/structs/EnumerableSet.sol | 792 ++ .../utils/structs/Heap.sol | 256 + .../utils/structs/MerkleTree.sol | 267 + .../utils/types/Time.sol | 133 + .../vendor/compound/ICompoundTimelock.sol | 86 + .../LICENSE | 661 + .../README.md | 97 + .../src/SVM.sol | 51 + .../src/SymTest.sol | 11 + .../.depcheckrc | 1 + .../.eslintrc.js | 79 + .../.github/workflows/build.yml | 93 + .../.gitignore | 20 + .../.solcover.js | 8 + .../.solhint.json | 12 + .../.solhintignore | 1 + .../LICENSE | 674 + .../README.md | 11 + ...bstraction_Incremental_Audit_Feb_2023.pdf" | Bin 0 -> 565821 bytes ...n Incremental Audit Report Feb 20 2024.pdf | Bin 0 -> 243905 bytes .../contracts/.npmignore | 2 + .../contracts/accounts/Simple7702Account.sol | 66 + .../contracts/accounts/SimpleAccount.sol | 110 + .../accounts/SimpleAccountFactory.sol | 56 + .../callback/TokenCallbackHandler.sol | 51 + .../contracts/core/BaseAccount.sol | 161 + .../contracts/core/BasePaymaster.sol | 151 + .../contracts/core/Eip7702Support.sol | 81 + .../contracts/core/EntryPoint.sol | 958 ++ .../contracts/core/EntryPointSimulations.sol | 215 + .../contracts/core/Helpers.sol | 135 + .../contracts/core/NonceManager.sol | 40 + .../contracts/core/SenderCreator.sol | 76 + .../contracts/core/StakeManager.sol | 149 + .../contracts/core/UserOperationLib.sol | 131 + .../contracts/interfaces/IAccount.sol | 39 + .../contracts/interfaces/IAccountExecute.sol | 20 + .../contracts/interfaces/IAggregator.sol | 44 + .../contracts/interfaces/IEntryPoint.sol | 222 + .../interfaces/IEntryPointSimulations.sol | 82 + .../contracts/interfaces/INonceManager.sol | 29 + .../contracts/interfaces/IPaymaster.sol | 63 + .../contracts/interfaces/ISenderCreator.sol | 21 + .../contracts/interfaces/IStakeManager.sol | 111 + .../interfaces/PackedUserOperation.sol | 28 + .../contracts/legacy/v06/IAccount06.sol | 34 + .../contracts/legacy/v06/IAggregator06.sol | 36 + .../contracts/legacy/v06/IEntryPoint06.sol | 204 + .../contracts/legacy/v06/INonceManager06.sol | 27 + .../contracts/legacy/v06/IPaymaster06.sol | 51 + .../contracts/legacy/v06/IStakeManager06.sol | 104 + .../contracts/legacy/v06/UserOperation06.sol | 30 + .../test/GasCalcPaymasterWithPostOp.sol | 25 + .../contracts/test/MaliciousAccount.sol | 31 + .../contracts/test/TestAggregatedAccount.sol | 31 + .../test/TestAggregatedAccountFactory.sol | 51 + .../contracts/test/TestCounter.sol | 34 + .../contracts/test/TestERC20.sol | 29 + .../test/TestEip7702DelegateAccount.sol | 23 + .../contracts/test/TestExecAccount.sol | 75 + .../contracts/test/TestExpirePaymaster.sol | 24 + .../contracts/test/TestExpiryAccount.sol | 48 + .../contracts/test/TestHelpers.sol | 19 + .../contracts/test/TestPaymasterAcceptAll.sol | 27 + .../test/TestPaymasterRevertCustomError.sol | 48 + .../test/TestPaymasterWithPostOp.sol | 37 + .../contracts/test/TestRevertAccount.sol | 23 + .../test/TestSignatureAggregator.sol | 53 + .../contracts/test/TestToken.sol | 15 + .../contracts/test/TestUniswap.sol | 60 + .../contracts/test/TestUtil.sol | 17 + .../contracts/test/TestWarmColdAccount.sol | 39 + .../contracts/test/TestWrappedNativeToken.sol | 29 + .../contracts/utils/Exec.sol | 71 + .../deploy/1_deploy_entrypoint.ts | 20 + .../deploy/2_deploy_SimpleAccountFactory.ts | 34 + .../deployments/ethereum/.chainId | 1 + .../deployments/ethereum/EntryPoint.json | 1090 ++ .../594e0595d5f1f4861d3b32a5f38cc32f.json | 120 + .../funding.json | 5 + .../gascalc/0-init-gas-checker.ts | 12 + .../gascalc/1-simple-wallet.gas.ts | 17 + .../gascalc/2-paymaster.gas.ts | 43 + .../gascalc/3-huge-tx-gas.ts | 17 + .../gascalc/4-paymaster-postop.gas.ts | 45 + .../gascalc/GasChecker.ts | 424 + .../hardhat.config.ts | 78 + .../reports/gas-checker.txt | 47 + .../scripts/check-gas-reports | 17 + .../scripts/docker-gascalc | 7 + .../scripts/docker-gascalc.yml | 23 + .../scripts/gascalc | 15 + .../scripts/geth.sh | 7 + .../scripts/hh-wrapper | 5 + .../scripts/postpack-contracts-package.sh | 6 + .../scripts/prepack-contracts-package.sh | 17 + .../scripts/sample-script.js | 32 + .../scripts/solcErrors | 12 + .../src/AASigner.ts | 401 + .../src/Create2Factory.ts | 125 + .../src/Utils.ts | 16 + .../src/runop.ts | 112 + .../test/0-create2factory.test.ts | 43 + .../test/GethExecutable.ts | 135 + .../test/UserOp.ts | 456 + .../test/UserOperation.ts | 32 + .../test/aa.init.ts | 6 + .../test/chaiHelper.ts | 65 + .../test/debugTx.ts | 26 + .../test/eip7702-wallet.test.ts | 143 + .../test/eip7702helpers.ts | 74 + .../test/entrypoint-7702.test.ts | 247 + .../test/entrypoint.test.ts | 1561 +++ .../test/entrypointsimulations.test.ts | 376 + .../test/helpers.test.ts | 50 + .../test/postop.test.ts | 104 + .../test/simple-wallet.test.ts | 163 + .../test/solidityTypes.ts | 11 + .../test/testExecAccount.test.ts | 55 + .../test/testutils.ts | 471 + .../tsconfig.json | 31 + .../yarn.lock | 10333 ++++++++++++++++ dependencies/solady-0.1.26/LICENSE.txt | 21 + dependencies/solady-0.1.26/README.md | 182 + dependencies/solady-0.1.26/js/solady.d.ts | 66 + dependencies/solady-0.1.26/js/solady.js | 255 + dependencies/solady-0.1.26/js/solady.test.js | 123 + dependencies/solady-0.1.26/src/Milady.sol | 79 + .../src/accounts/EIP7702Proxy.sol | 182 + .../solady-0.1.26/src/accounts/ERC1271.sol | 327 + .../solady-0.1.26/src/accounts/ERC4337.sol | 428 + .../src/accounts/ERC4337Factory.sol | 70 + .../solady-0.1.26/src/accounts/ERC6551.sol | 422 + .../src/accounts/ERC6551Proxy.sol | 78 + .../solady-0.1.26/src/accounts/ERC7821.sol | 246 + .../solady-0.1.26/src/accounts/LibEIP7702.sol | 237 + .../solady-0.1.26/src/accounts/LibERC6551.sol | 232 + .../solady-0.1.26/src/accounts/LibERC7579.sol | 335 + .../solady-0.1.26/src/accounts/Receiver.sol | 66 + .../solady-0.1.26/src/accounts/Timelock.sol | 450 + .../src/auth/EnumerableRoles.sol | 315 + .../solady-0.1.26/src/auth/Ownable.sol | 278 + .../solady-0.1.26/src/auth/OwnableRoles.sol | 535 + .../solady-0.1.26/src/auth/TimedRoles.sol | 282 + .../solady-0.1.26/src/tokens/ERC1155.sol | 1120 ++ .../solady-0.1.26/src/tokens/ERC20.sol | 670 + .../solady-0.1.26/src/tokens/ERC20Votes.sol | 458 + .../solady-0.1.26/src/tokens/ERC2981.sol | 162 + .../solady-0.1.26/src/tokens/ERC4626.sol | 527 + .../solady-0.1.26/src/tokens/ERC6909.sol | 547 + .../solady-0.1.26/src/tokens/ERC721.sol | 913 ++ .../solady-0.1.26/src/tokens/WETH.sol | 58 + .../src/tokens/ext/zksync/ERC1155.sol | 1143 ++ .../src/tokens/ext/zksync/ERC721.sol | 916 ++ .../solady-0.1.26/src/utils/Base58.sol | 205 + .../solady-0.1.26/src/utils/Base64.sol | 175 + .../solady-0.1.26/src/utils/BlockHashLib.sol | 38 + .../solady-0.1.26/src/utils/CREATE3.sol | 128 + .../src/utils/CallContextChecker.sol | 100 + .../solady-0.1.26/src/utils/DateTimeLib.sol | 512 + .../src/utils/DeploylessPredeployQueryer.sol | 91 + .../src/utils/DynamicArrayLib.sol | 1020 ++ .../src/utils/DynamicBufferLib.sol | 1313 ++ .../solady-0.1.26/src/utils/ECDSA.sol | 442 + .../solady-0.1.26/src/utils/EIP712.sol | 300 + .../src/utils/ERC1967Factory.sol | 418 + .../src/utils/ERC1967FactoryConstants.sol | 45 + .../src/utils/EfficientHashLib.sol | 934 ++ .../src/utils/EnumerableMapLib.sol | 820 ++ .../src/utils/EnumerableSetLib.sol | 918 ++ .../src/utils/FixedPointMathLib.sol | 1312 ++ .../solady-0.1.26/src/utils/GasBurnerLib.sol | 72 + .../solady-0.1.26/src/utils/Initializable.sol | 196 + .../solady-0.1.26/src/utils/JSONParserLib.sol | 815 ++ .../solady-0.1.26/src/utils/LibBit.sol | 309 + .../solady-0.1.26/src/utils/LibBitmap.sol | 236 + .../solady-0.1.26/src/utils/LibBytes.sol | 888 ++ .../solady-0.1.26/src/utils/LibCall.sol | 220 + .../solady-0.1.26/src/utils/LibClone.sol | 2863 +++++ .../solady-0.1.26/src/utils/LibMap.sol | 309 + .../solady-0.1.26/src/utils/LibPRNG.sol | 500 + .../solady-0.1.26/src/utils/LibRLP.sol | 391 + .../solady-0.1.26/src/utils/LibSort.sol | 942 ++ .../solady-0.1.26/src/utils/LibStorage.sol | 85 + .../solady-0.1.26/src/utils/LibString.sol | 977 ++ .../solady-0.1.26/src/utils/LibTransient.sol | 963 ++ .../solady-0.1.26/src/utils/LibZip.sol | 327 + .../solady-0.1.26/src/utils/Lifebuoy.sol | 316 + .../src/utils/MerkleProofLib.sol | 309 + .../solady-0.1.26/src/utils/MerkleTreeLib.sol | 289 + .../src/utils/MetadataReaderLib.sol | 223 + .../solady-0.1.26/src/utils/MinHeapLib.sol | 576 + .../solady-0.1.26/src/utils/Multicallable.sol | 112 + dependencies/solady-0.1.26/src/utils/P256.sol | 179 + .../src/utils/RedBlackTreeLib.sol | 718 ++ .../src/utils/ReentrancyGuard.sol | 55 + .../src/utils/ReentrancyGuardTransient.sol | 123 + .../solady-0.1.26/src/utils/SSTORE2.sol | 259 + .../solady-0.1.26/src/utils/SafeCastLib.sol | 673 + .../src/utils/SafeTransferLib.sol | 683 + .../solady-0.1.26/src/utils/SemVerLib.sol | 67 + .../src/utils/SignatureCheckerLib.sol | 527 + .../src/utils/UUPSUpgradeable.sol | 105 + .../src/utils/UpgradeableBeacon.sol | 190 + .../solady-0.1.26/src/utils/WebAuthn.sol | 336 + .../ext/delegatexyz/DelegateCheckerLib.sol | 341 + .../src/utils/ext/ithaca/BLS.sol | 354 + .../utils/ext/zksync/ERC1967BeaconProxy.sol | 78 + .../src/utils/ext/zksync/ERC1967Factory.sol | 457 + .../ext/zksync/ERC1967FactoryConstants.sol | 9 + .../src/utils/ext/zksync/ERC1967Proxy.sol | 82 + .../src/utils/ext/zksync/SafeTransferLib.sol | 387 + .../utils/ext/zksync/SignatureCheckerLib.sol | 367 + .../utils/ext/zksync/SingleUseETHVault.sol | 50 + .../utils/ext/zksync/UpgradeableBeacon.sol | 62 + .../zksync/delegatexyz/DelegateCheckerLib.sol | 301 + .../src/utils/g/DynamicArrayLib.sol | 1024 ++ .../src/utils/g/DynamicBufferLib.sol | 1317 ++ .../src/utils/g/EnumerableMapLib.sol | 832 ++ .../src/utils/g/EnumerableSetLib.sol | 926 ++ .../src/utils/g/JSONParserLib.sol | 819 ++ .../solady-0.1.26/src/utils/g/LibBitmap.sol | 240 + .../solady-0.1.26/src/utils/g/LibBytes.sol | 892 ++ .../solady-0.1.26/src/utils/g/LibMap.sol | 318 + .../solady-0.1.26/src/utils/g/LibPRNG.sol | 505 + .../solady-0.1.26/src/utils/g/LibRLP.sol | 395 + .../solady-0.1.26/src/utils/g/LibStorage.sol | 90 + .../solady-0.1.26/src/utils/g/LibString.sol | 981 ++ .../src/utils/g/LibTransient.sol | 973 ++ .../solady-0.1.26/src/utils/g/MinHeapLib.sol | 581 + .../src/utils/g/RedBlackTreeLib.sol | 722 ++ .../solady-0.1.26/src/utils/g/WebAuthn.sol | 340 + .../solady-0.1.26/src/utils/legacy/CWIA.sol | 387 + .../src/utils/legacy/LibCWIA.sol | 387 + foundry.lock | 5 +- foundry.toml | 10 +- lib/account-abstraction | 1 - lib/halmos-cheatcodes | 1 - lib/openzeppelin-contracts | 1 - lib/solady | 1 - remappings.txt | 12 +- snapshots/Kernel7702Test.json | 4 +- snapshots/KernelECDSATest.json | 4 +- snapshots/KernelFactoryTest.json | 2 +- snapshots/KernelImmutableECDSATest.json | 4 +- snapshots/KernelTest.json | 4 +- soldeer.lock | 27 + src/Kernel.sol | 27 +- src/Kernel7702.sol | 4 + src/KernelFactory.sol | 8 +- src/KernelHelper.sol | 4 +- src/Staker.sol | 22 +- src/core/ExecutionManager.sol | 7 +- src/core/ModuleManager.sol | 2 +- src/core/ValidationManager.sol | 12 +- src/interfaces/IERC7579Modules.sol | 13 +- src/lib/ERC1271.sol | 71 +- test/Kernel.t.sol | 20 +- test/Kernel7702.t.sol | 16 +- test/KernelECDSA.t.sol | 15 +- test/KernelERC1271Test.sol | 2 +- test/KernelFactory.t.sol | 30 +- test/KernelImmutableECDSA.t.sol | 10 +- test/KernelTestBase.sol | 11 +- test/KernelUserOpTest.sol | 107 +- test/KernelValidatorTest.sol | 38 +- test/mock/MockFallback.sol | 9 +- test/mock/MockKernel.sol | 4 +- 686 files changed, 166017 insertions(+), 267 deletions(-) create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/README.md create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/access/AccessControl.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/access/IAccessControl.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/access/Ownable.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/access/Ownable2Step.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/access/extensions/AccessControlDefaultAdminRules.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/access/extensions/AccessControlEnumerable.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/access/extensions/IAccessControlDefaultAdminRules.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/access/extensions/IAccessControlEnumerable.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/access/manager/AccessManaged.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/access/manager/AccessManager.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/access/manager/AuthorityUtils.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/access/manager/IAccessManaged.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/access/manager/IAccessManager.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/access/manager/IAuthority.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/account/Account.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/account/extensions/draft-AccountERC7579.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/account/extensions/draft-AccountERC7579Hooked.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/account/extensions/draft-ERC7821.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/account/utils/EIP7702Utils.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/account/utils/draft-ERC4337Utils.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/account/utils/draft-ERC7579Utils.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/AbstractSigner.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/AccessControl.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/AccessControlDefaultAdminRules.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/AccessControlEnumerable.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/AccessManaged.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/AccessManager.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Account.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/AccountERC7579.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/AccountERC7579Hooked.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Address.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Arrays.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/AuthorityUtils.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Base64.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/BeaconProxy.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/BitMaps.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Blockhash.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Bytes.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/CAIP10.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/CAIP2.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Calldata.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Checkpoints.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/CircularBuffer.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Clones.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Comparators.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Context.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Create2.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/DoubleEndedQueue.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ECDSA.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/EIP712.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/EIP7702Utils.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC1155.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC1155Burnable.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC1155Holder.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC1155Pausable.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC1155Supply.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC1155URIStorage.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC1155Utils.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC1363.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC1363Utils.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC165.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC165Checker.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC1967Proxy.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC1967Utils.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC20.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC20Bridgeable.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC20Burnable.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC20Capped.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC20FlashMint.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC20Pausable.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC20Permit.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC20TemporaryApproval.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC20Votes.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC20Wrapper.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC2771Context.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC2771Forwarder.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC2981.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC4337Utils.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC4626.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC6909.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC6909ContentURI.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC6909Metadata.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC6909TokenSupply.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC721.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC721Burnable.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC721Consecutive.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC721Enumerable.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC721Holder.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC721Pausable.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC721Royalty.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC721URIStorage.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC721Utils.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC721Votes.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC721Wrapper.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC7579Utils.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC7739.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC7739Utils.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC7821.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC7913P256Verifier.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC7913RSAVerifier.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/EnumerableMap.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/EnumerableSet.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Errors.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Governor.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/GovernorCountingFractional.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/GovernorCountingOverridable.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/GovernorCountingSimple.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/GovernorNoncesKeyed.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/GovernorPreventLateQuorum.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/GovernorProposalGuardian.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/GovernorSequentialProposalId.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/GovernorSettings.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/GovernorStorage.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/GovernorSuperQuorum.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/GovernorTimelockAccess.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/GovernorTimelockCompound.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/GovernorTimelockControl.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/GovernorVotes.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/GovernorVotesQuorumFraction.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/GovernorVotesSuperQuorumFraction.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Hashes.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Heap.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IAccessControl.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IAccessControlDefaultAdminRules.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IAccessControlEnumerable.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IAccessManaged.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IAccessManager.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IAccount.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IAccountExecute.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IAggregator.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IAuthority.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IBeacon.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ICompoundTimelock.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC1155.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC1155Errors.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC1155MetadataURI.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC1155Receiver.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC1271.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC1363.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC1363Receiver.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC1363Spender.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC165.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC1820Implementer.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC1820Registry.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC1822Proxiable.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC1967.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC20.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC20Errors.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC20Metadata.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC20Permit.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC2309.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC2612.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC2981.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC3156FlashBorrower.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC3156FlashLender.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC4626.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC4906.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC5267.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC5313.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC5805.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC6372.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC6909.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC6909ContentURI.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC6909Metadata.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC6909TokenSupply.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC721.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC721Enumerable.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC721Errors.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC721Metadata.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC721Receiver.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC7579AccountConfig.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC7579Execution.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC7579Hook.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC7579Module.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC7579ModuleConfig.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC7579Validator.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC7674.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC777.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC777Recipient.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC777Sender.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC7802.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC7821.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC7913SignatureVerifier.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IEntryPoint.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IEntryPointExtra.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IEntryPointNonces.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IEntryPointStake.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IGovernor.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IPaymaster.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ITransparentUpgradeableProxy.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IVotes.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Initializable.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Math.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/MerkleProof.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/MerkleTree.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/MessageHashUtils.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/MultiSignerERC7913.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/MultiSignerERC7913Weighted.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Multicall.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Nonces.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/NoncesKeyed.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Ownable.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Ownable2Step.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/P256.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Packing.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Panic.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Pausable.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Proxy.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ProxyAdmin.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/RSA.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ReentrancyGuard.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ReentrancyGuardTransient.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/SafeCast.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/SafeERC20.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ShortStrings.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/SignatureChecker.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/SignedMath.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/SignerECDSA.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/SignerERC7702.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/SignerERC7913.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/SignerP256.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/SignerRSA.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/SlotDerivation.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/StorageSlot.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Strings.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Time.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/TimelockController.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/TransientSlot.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/TransparentUpgradeableProxy.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/UUPSUpgradeable.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/UpgradeableBeacon.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/VestingWallet.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/VestingWalletCliff.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Votes.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/build/contracts/VotesExtended.json create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/finance/VestingWallet.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/finance/VestingWalletCliff.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/governance/Governor.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/governance/IGovernor.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/governance/TimelockController.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/governance/extensions/GovernorCountingFractional.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/governance/extensions/GovernorCountingOverridable.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/governance/extensions/GovernorCountingSimple.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/governance/extensions/GovernorNoncesKeyed.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/governance/extensions/GovernorPreventLateQuorum.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/governance/extensions/GovernorProposalGuardian.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/governance/extensions/GovernorSequentialProposalId.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/governance/extensions/GovernorSettings.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/governance/extensions/GovernorStorage.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/governance/extensions/GovernorSuperQuorum.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/governance/extensions/GovernorTimelockAccess.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/governance/extensions/GovernorTimelockCompound.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/governance/extensions/GovernorTimelockControl.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/governance/extensions/GovernorVotes.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/governance/extensions/GovernorVotesQuorumFraction.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/governance/extensions/GovernorVotesSuperQuorumFraction.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/governance/utils/IVotes.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/governance/utils/Votes.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/governance/utils/VotesExtended.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC1155.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC1155MetadataURI.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC1155Receiver.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC1271.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC1363.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC1363Receiver.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC1363Spender.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC165.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC1820Implementer.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC1820Registry.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC1967.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC20.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC20Metadata.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC2309.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC2612.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC2981.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC3156.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC3156FlashBorrower.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC3156FlashLender.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC4626.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC4906.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC5267.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC5313.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC5805.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC6372.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC721.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC721Enumerable.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC721Metadata.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC721Receiver.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC777.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC777Recipient.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC777Sender.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC7913.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/interfaces/draft-IERC1822.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/interfaces/draft-IERC4337.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/interfaces/draft-IERC6093.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/interfaces/draft-IERC6909.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/interfaces/draft-IERC7579.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/interfaces/draft-IERC7674.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/interfaces/draft-IERC7802.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/interfaces/draft-IERC7821.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/metatx/ERC2771Context.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/metatx/ERC2771Forwarder.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/proxy/Clones.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/proxy/ERC1967/ERC1967Proxy.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/proxy/ERC1967/ERC1967Utils.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/proxy/Proxy.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/proxy/beacon/BeaconProxy.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/proxy/beacon/IBeacon.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/proxy/beacon/UpgradeableBeacon.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/proxy/transparent/ProxyAdmin.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/proxy/transparent/TransparentUpgradeableProxy.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/proxy/utils/Initializable.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/proxy/utils/UUPSUpgradeable.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/token/ERC1155/ERC1155.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/token/ERC1155/IERC1155.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/token/ERC1155/IERC1155Receiver.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/token/ERC1155/extensions/ERC1155Burnable.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/token/ERC1155/extensions/ERC1155Pausable.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/token/ERC1155/extensions/ERC1155Supply.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/token/ERC1155/extensions/ERC1155URIStorage.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/token/ERC1155/extensions/IERC1155MetadataURI.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/token/ERC1155/utils/ERC1155Holder.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/token/ERC1155/utils/ERC1155Utils.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/ERC20.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/IERC20.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/extensions/ERC1363.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/extensions/ERC20Burnable.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/extensions/ERC20Capped.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/extensions/ERC20FlashMint.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/extensions/ERC20Pausable.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/extensions/ERC20Permit.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/extensions/ERC20Votes.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/extensions/ERC20Wrapper.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/extensions/ERC4626.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/extensions/IERC20Metadata.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/extensions/IERC20Permit.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/extensions/draft-ERC20Bridgeable.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/extensions/draft-ERC20TemporaryApproval.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/utils/ERC1363Utils.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/utils/SafeERC20.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/token/ERC6909/draft-ERC6909.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/token/ERC6909/extensions/draft-ERC6909ContentURI.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/token/ERC6909/extensions/draft-ERC6909Metadata.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/token/ERC6909/extensions/draft-ERC6909TokenSupply.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/token/ERC721/ERC721.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/token/ERC721/IERC721.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/token/ERC721/IERC721Receiver.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/token/ERC721/extensions/ERC721Burnable.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/token/ERC721/extensions/ERC721Consecutive.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/token/ERC721/extensions/ERC721Enumerable.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/token/ERC721/extensions/ERC721Pausable.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/token/ERC721/extensions/ERC721Royalty.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/token/ERC721/extensions/ERC721URIStorage.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/token/ERC721/extensions/ERC721Votes.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/token/ERC721/extensions/ERC721Wrapper.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/token/ERC721/extensions/IERC721Enumerable.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/token/ERC721/extensions/IERC721Metadata.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/token/ERC721/utils/ERC721Holder.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/token/ERC721/utils/ERC721Utils.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/token/common/ERC2981.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/utils/Address.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/utils/Arrays.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/utils/Base64.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/utils/Blockhash.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/utils/Bytes.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/utils/CAIP10.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/utils/CAIP2.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/utils/Calldata.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/utils/Comparators.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/utils/Context.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/utils/Create2.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/utils/Errors.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/utils/Multicall.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/utils/Nonces.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/utils/NoncesKeyed.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/utils/Packing.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/utils/Panic.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/utils/Pausable.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/utils/ReentrancyGuard.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/utils/ReentrancyGuardTransient.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/utils/ShortStrings.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/utils/SlotDerivation.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/utils/StorageSlot.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/utils/Strings.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/utils/TransientSlot.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/ECDSA.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/EIP712.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/Hashes.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/MerkleProof.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/MessageHashUtils.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/P256.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/RSA.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/SignatureChecker.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/draft-ERC7739Utils.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/signers/AbstractSigner.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/signers/MultiSignerERC7913.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/signers/MultiSignerERC7913Weighted.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/signers/SignerECDSA.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/signers/SignerERC7702.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/signers/SignerERC7913.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/signers/SignerP256.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/signers/SignerRSA.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/signers/draft-ERC7739.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/verifiers/ERC7913P256Verifier.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/verifiers/ERC7913RSAVerifier.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/utils/introspection/ERC165.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/utils/introspection/ERC165Checker.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/utils/introspection/IERC165.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/utils/math/Math.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/utils/math/SafeCast.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/utils/math/SignedMath.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/utils/structs/BitMaps.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/utils/structs/Checkpoints.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/utils/structs/CircularBuffer.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/utils/structs/DoubleEndedQueue.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/utils/structs/EnumerableMap.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/utils/structs/EnumerableSet.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/utils/structs/Heap.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/utils/structs/MerkleTree.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/utils/types/Time.sol create mode 100644 dependencies/@openzeppelin-contracts-5.4.0/vendor/compound/ICompoundTimelock.sol create mode 100644 dependencies/a16z-halmos-cheatcodes-6da4e692c357ba6d641a2e677a28298cac9f76ab/LICENSE create mode 100644 dependencies/a16z-halmos-cheatcodes-6da4e692c357ba6d641a2e677a28298cac9f76ab/README.md create mode 100644 dependencies/a16z-halmos-cheatcodes-6da4e692c357ba6d641a2e677a28298cac9f76ab/src/SVM.sol create mode 100644 dependencies/a16z-halmos-cheatcodes-6da4e692c357ba6d641a2e677a28298cac9f76ab/src/SymTest.sol create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/.depcheckrc create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/.eslintrc.js create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/.github/workflows/build.yml create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/.gitignore create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/.solcover.js create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/.solhint.json create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/.solhintignore create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/LICENSE create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/README.md create mode 100644 "dependencies/eth-infinitism-account-abstraction-0.8.0/audits/EIP_4337_\342\200\223_Ethereum_Account_Abstraction_Incremental_Audit_Feb_2023.pdf" create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/audits/ERC-4337 Account Abstraction Incremental Audit Report Feb 20 2024.pdf create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/.npmignore create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/accounts/Simple7702Account.sol create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/accounts/SimpleAccount.sol create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/accounts/SimpleAccountFactory.sol create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/accounts/callback/TokenCallbackHandler.sol create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/BaseAccount.sol create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/BasePaymaster.sol create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/Eip7702Support.sol create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/EntryPoint.sol create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/EntryPointSimulations.sol create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/Helpers.sol create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/NonceManager.sol create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/SenderCreator.sol create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/StakeManager.sol create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/UserOperationLib.sol create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/interfaces/IAccount.sol create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/interfaces/IAccountExecute.sol create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/interfaces/IAggregator.sol create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/interfaces/IEntryPoint.sol create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/interfaces/IEntryPointSimulations.sol create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/interfaces/INonceManager.sol create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/interfaces/IPaymaster.sol create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/interfaces/ISenderCreator.sol create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/interfaces/IStakeManager.sol create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/interfaces/PackedUserOperation.sol create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/legacy/v06/IAccount06.sol create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/legacy/v06/IAggregator06.sol create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/legacy/v06/IEntryPoint06.sol create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/legacy/v06/INonceManager06.sol create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/legacy/v06/IPaymaster06.sol create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/legacy/v06/IStakeManager06.sol create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/legacy/v06/UserOperation06.sol create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/GasCalcPaymasterWithPostOp.sol create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/MaliciousAccount.sol create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestAggregatedAccount.sol create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestAggregatedAccountFactory.sol create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestCounter.sol create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestERC20.sol create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestEip7702DelegateAccount.sol create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestExecAccount.sol create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestExpirePaymaster.sol create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestExpiryAccount.sol create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestHelpers.sol create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestPaymasterAcceptAll.sol create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestPaymasterRevertCustomError.sol create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestPaymasterWithPostOp.sol create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestRevertAccount.sol create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestSignatureAggregator.sol create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestToken.sol create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestUniswap.sol create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestUtil.sol create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestWarmColdAccount.sol create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestWrappedNativeToken.sol create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/utils/Exec.sol create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/deploy/1_deploy_entrypoint.ts create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/deploy/2_deploy_SimpleAccountFactory.ts create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/deployments/ethereum/.chainId create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/deployments/ethereum/EntryPoint.json create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/deployments/ethereum/solcInputs/594e0595d5f1f4861d3b32a5f38cc32f.json create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/funding.json create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/gascalc/0-init-gas-checker.ts create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/gascalc/1-simple-wallet.gas.ts create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/gascalc/2-paymaster.gas.ts create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/gascalc/3-huge-tx-gas.ts create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/gascalc/4-paymaster-postop.gas.ts create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/gascalc/GasChecker.ts create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/hardhat.config.ts create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/reports/gas-checker.txt create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/scripts/check-gas-reports create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/scripts/docker-gascalc create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/scripts/docker-gascalc.yml create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/scripts/gascalc create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/scripts/geth.sh create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/scripts/hh-wrapper create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/scripts/postpack-contracts-package.sh create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/scripts/prepack-contracts-package.sh create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/scripts/sample-script.js create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/scripts/solcErrors create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/src/AASigner.ts create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/src/Create2Factory.ts create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/src/Utils.ts create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/src/runop.ts create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/test/0-create2factory.test.ts create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/test/GethExecutable.ts create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/test/UserOp.ts create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/test/UserOperation.ts create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/test/aa.init.ts create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/test/chaiHelper.ts create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/test/debugTx.ts create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/test/eip7702-wallet.test.ts create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/test/eip7702helpers.ts create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/test/entrypoint-7702.test.ts create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/test/entrypoint.test.ts create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/test/entrypointsimulations.test.ts create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/test/helpers.test.ts create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/test/postop.test.ts create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/test/simple-wallet.test.ts create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/test/solidityTypes.ts create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/test/testExecAccount.test.ts create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/test/testutils.ts create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/tsconfig.json create mode 100644 dependencies/eth-infinitism-account-abstraction-0.8.0/yarn.lock create mode 100644 dependencies/solady-0.1.26/LICENSE.txt create mode 100644 dependencies/solady-0.1.26/README.md create mode 100644 dependencies/solady-0.1.26/js/solady.d.ts create mode 100644 dependencies/solady-0.1.26/js/solady.js create mode 100644 dependencies/solady-0.1.26/js/solady.test.js create mode 100644 dependencies/solady-0.1.26/src/Milady.sol create mode 100644 dependencies/solady-0.1.26/src/accounts/EIP7702Proxy.sol create mode 100644 dependencies/solady-0.1.26/src/accounts/ERC1271.sol create mode 100644 dependencies/solady-0.1.26/src/accounts/ERC4337.sol create mode 100644 dependencies/solady-0.1.26/src/accounts/ERC4337Factory.sol create mode 100644 dependencies/solady-0.1.26/src/accounts/ERC6551.sol create mode 100644 dependencies/solady-0.1.26/src/accounts/ERC6551Proxy.sol create mode 100644 dependencies/solady-0.1.26/src/accounts/ERC7821.sol create mode 100644 dependencies/solady-0.1.26/src/accounts/LibEIP7702.sol create mode 100644 dependencies/solady-0.1.26/src/accounts/LibERC6551.sol create mode 100644 dependencies/solady-0.1.26/src/accounts/LibERC7579.sol create mode 100644 dependencies/solady-0.1.26/src/accounts/Receiver.sol create mode 100644 dependencies/solady-0.1.26/src/accounts/Timelock.sol create mode 100644 dependencies/solady-0.1.26/src/auth/EnumerableRoles.sol create mode 100644 dependencies/solady-0.1.26/src/auth/Ownable.sol create mode 100644 dependencies/solady-0.1.26/src/auth/OwnableRoles.sol create mode 100644 dependencies/solady-0.1.26/src/auth/TimedRoles.sol create mode 100644 dependencies/solady-0.1.26/src/tokens/ERC1155.sol create mode 100644 dependencies/solady-0.1.26/src/tokens/ERC20.sol create mode 100644 dependencies/solady-0.1.26/src/tokens/ERC20Votes.sol create mode 100644 dependencies/solady-0.1.26/src/tokens/ERC2981.sol create mode 100644 dependencies/solady-0.1.26/src/tokens/ERC4626.sol create mode 100644 dependencies/solady-0.1.26/src/tokens/ERC6909.sol create mode 100644 dependencies/solady-0.1.26/src/tokens/ERC721.sol create mode 100644 dependencies/solady-0.1.26/src/tokens/WETH.sol create mode 100644 dependencies/solady-0.1.26/src/tokens/ext/zksync/ERC1155.sol create mode 100644 dependencies/solady-0.1.26/src/tokens/ext/zksync/ERC721.sol create mode 100644 dependencies/solady-0.1.26/src/utils/Base58.sol create mode 100644 dependencies/solady-0.1.26/src/utils/Base64.sol create mode 100644 dependencies/solady-0.1.26/src/utils/BlockHashLib.sol create mode 100644 dependencies/solady-0.1.26/src/utils/CREATE3.sol create mode 100644 dependencies/solady-0.1.26/src/utils/CallContextChecker.sol create mode 100644 dependencies/solady-0.1.26/src/utils/DateTimeLib.sol create mode 100644 dependencies/solady-0.1.26/src/utils/DeploylessPredeployQueryer.sol create mode 100644 dependencies/solady-0.1.26/src/utils/DynamicArrayLib.sol create mode 100644 dependencies/solady-0.1.26/src/utils/DynamicBufferLib.sol create mode 100644 dependencies/solady-0.1.26/src/utils/ECDSA.sol create mode 100644 dependencies/solady-0.1.26/src/utils/EIP712.sol create mode 100644 dependencies/solady-0.1.26/src/utils/ERC1967Factory.sol create mode 100644 dependencies/solady-0.1.26/src/utils/ERC1967FactoryConstants.sol create mode 100644 dependencies/solady-0.1.26/src/utils/EfficientHashLib.sol create mode 100644 dependencies/solady-0.1.26/src/utils/EnumerableMapLib.sol create mode 100644 dependencies/solady-0.1.26/src/utils/EnumerableSetLib.sol create mode 100644 dependencies/solady-0.1.26/src/utils/FixedPointMathLib.sol create mode 100644 dependencies/solady-0.1.26/src/utils/GasBurnerLib.sol create mode 100644 dependencies/solady-0.1.26/src/utils/Initializable.sol create mode 100644 dependencies/solady-0.1.26/src/utils/JSONParserLib.sol create mode 100644 dependencies/solady-0.1.26/src/utils/LibBit.sol create mode 100644 dependencies/solady-0.1.26/src/utils/LibBitmap.sol create mode 100644 dependencies/solady-0.1.26/src/utils/LibBytes.sol create mode 100644 dependencies/solady-0.1.26/src/utils/LibCall.sol create mode 100644 dependencies/solady-0.1.26/src/utils/LibClone.sol create mode 100644 dependencies/solady-0.1.26/src/utils/LibMap.sol create mode 100644 dependencies/solady-0.1.26/src/utils/LibPRNG.sol create mode 100644 dependencies/solady-0.1.26/src/utils/LibRLP.sol create mode 100644 dependencies/solady-0.1.26/src/utils/LibSort.sol create mode 100644 dependencies/solady-0.1.26/src/utils/LibStorage.sol create mode 100644 dependencies/solady-0.1.26/src/utils/LibString.sol create mode 100644 dependencies/solady-0.1.26/src/utils/LibTransient.sol create mode 100644 dependencies/solady-0.1.26/src/utils/LibZip.sol create mode 100644 dependencies/solady-0.1.26/src/utils/Lifebuoy.sol create mode 100644 dependencies/solady-0.1.26/src/utils/MerkleProofLib.sol create mode 100644 dependencies/solady-0.1.26/src/utils/MerkleTreeLib.sol create mode 100644 dependencies/solady-0.1.26/src/utils/MetadataReaderLib.sol create mode 100644 dependencies/solady-0.1.26/src/utils/MinHeapLib.sol create mode 100644 dependencies/solady-0.1.26/src/utils/Multicallable.sol create mode 100644 dependencies/solady-0.1.26/src/utils/P256.sol create mode 100644 dependencies/solady-0.1.26/src/utils/RedBlackTreeLib.sol create mode 100644 dependencies/solady-0.1.26/src/utils/ReentrancyGuard.sol create mode 100644 dependencies/solady-0.1.26/src/utils/ReentrancyGuardTransient.sol create mode 100644 dependencies/solady-0.1.26/src/utils/SSTORE2.sol create mode 100644 dependencies/solady-0.1.26/src/utils/SafeCastLib.sol create mode 100644 dependencies/solady-0.1.26/src/utils/SafeTransferLib.sol create mode 100644 dependencies/solady-0.1.26/src/utils/SemVerLib.sol create mode 100644 dependencies/solady-0.1.26/src/utils/SignatureCheckerLib.sol create mode 100644 dependencies/solady-0.1.26/src/utils/UUPSUpgradeable.sol create mode 100644 dependencies/solady-0.1.26/src/utils/UpgradeableBeacon.sol create mode 100644 dependencies/solady-0.1.26/src/utils/WebAuthn.sol create mode 100644 dependencies/solady-0.1.26/src/utils/ext/delegatexyz/DelegateCheckerLib.sol create mode 100644 dependencies/solady-0.1.26/src/utils/ext/ithaca/BLS.sol create mode 100644 dependencies/solady-0.1.26/src/utils/ext/zksync/ERC1967BeaconProxy.sol create mode 100644 dependencies/solady-0.1.26/src/utils/ext/zksync/ERC1967Factory.sol create mode 100644 dependencies/solady-0.1.26/src/utils/ext/zksync/ERC1967FactoryConstants.sol create mode 100644 dependencies/solady-0.1.26/src/utils/ext/zksync/ERC1967Proxy.sol create mode 100644 dependencies/solady-0.1.26/src/utils/ext/zksync/SafeTransferLib.sol create mode 100644 dependencies/solady-0.1.26/src/utils/ext/zksync/SignatureCheckerLib.sol create mode 100644 dependencies/solady-0.1.26/src/utils/ext/zksync/SingleUseETHVault.sol create mode 100644 dependencies/solady-0.1.26/src/utils/ext/zksync/UpgradeableBeacon.sol create mode 100644 dependencies/solady-0.1.26/src/utils/ext/zksync/delegatexyz/DelegateCheckerLib.sol create mode 100644 dependencies/solady-0.1.26/src/utils/g/DynamicArrayLib.sol create mode 100644 dependencies/solady-0.1.26/src/utils/g/DynamicBufferLib.sol create mode 100644 dependencies/solady-0.1.26/src/utils/g/EnumerableMapLib.sol create mode 100644 dependencies/solady-0.1.26/src/utils/g/EnumerableSetLib.sol create mode 100644 dependencies/solady-0.1.26/src/utils/g/JSONParserLib.sol create mode 100644 dependencies/solady-0.1.26/src/utils/g/LibBitmap.sol create mode 100644 dependencies/solady-0.1.26/src/utils/g/LibBytes.sol create mode 100644 dependencies/solady-0.1.26/src/utils/g/LibMap.sol create mode 100644 dependencies/solady-0.1.26/src/utils/g/LibPRNG.sol create mode 100644 dependencies/solady-0.1.26/src/utils/g/LibRLP.sol create mode 100644 dependencies/solady-0.1.26/src/utils/g/LibStorage.sol create mode 100644 dependencies/solady-0.1.26/src/utils/g/LibString.sol create mode 100644 dependencies/solady-0.1.26/src/utils/g/LibTransient.sol create mode 100644 dependencies/solady-0.1.26/src/utils/g/MinHeapLib.sol create mode 100644 dependencies/solady-0.1.26/src/utils/g/RedBlackTreeLib.sol create mode 100644 dependencies/solady-0.1.26/src/utils/g/WebAuthn.sol create mode 100644 dependencies/solady-0.1.26/src/utils/legacy/CWIA.sol create mode 100644 dependencies/solady-0.1.26/src/utils/legacy/LibCWIA.sol delete mode 160000 lib/account-abstraction delete mode 160000 lib/halmos-cheatcodes delete mode 160000 lib/openzeppelin-contracts delete mode 160000 lib/solady create mode 100644 soldeer.lock diff --git a/.gitmodules b/.gitmodules index 7c0dce29..888d42dc 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,16 +1,3 @@ [submodule "lib/forge-std"] path = lib/forge-std url = https://github.com/foundry-rs/forge-std -[submodule "lib/account-abstraction"] - path = lib/account-abstraction - url = https://github.com/eth-infinitism/account-abstraction - branch = develop -[submodule "lib/solady"] - path = lib/solady - url = https://github.com/vectorized/solady -[submodule "lib/halmos-cheatcodes"] - path = lib/halmos-cheatcodes - url = https://github.com/a16z/halmos-cheatcodes -[submodule "lib/openzeppelin-contracts"] - path = lib/openzeppelin-contracts - url = https://github.com/openzeppelin/openzeppelin-contracts diff --git a/dependencies/@openzeppelin-contracts-5.4.0/README.md b/dependencies/@openzeppelin-contracts-5.4.0/README.md new file mode 100644 index 00000000..2f92281b --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/README.md @@ -0,0 +1,108 @@ +# OpenZeppelin + +[![Github Release](https://img.shields.io/github/v/tag/OpenZeppelin/openzeppelin-contracts.svg?filter=v*&sort=semver&label=github)](https://github.com/OpenZeppelin/openzeppelin-contracts/releases/latest) +[![NPM Package](https://img.shields.io/npm/v/@openzeppelin/contracts.svg)](https://www.npmjs.org/package/@openzeppelin/contracts) +[![Coverage Status](https://codecov.io/gh/OpenZeppelin/openzeppelin-contracts/graph/badge.svg)](https://codecov.io/gh/OpenZeppelin/openzeppelin-contracts) +[![GitPOAPs](https://public-api.gitpoap.io/v1/repo/OpenZeppelin/openzeppelin-contracts/badge)](https://www.gitpoap.io/gh/OpenZeppelin/openzeppelin-contracts) +[![Docs](https://img.shields.io/badge/docs-%F0%9F%93%84-yellow)](https://docs.openzeppelin.com/contracts) +[![Forum](https://img.shields.io/badge/forum-%F0%9F%92%AC-yellow)](https://forum.openzeppelin.com/) + +**A library for secure smart contract development.** Build on a solid foundation of community-vetted code. + + * Implementations of standards like [ERC20](https://docs.openzeppelin.com/contracts/erc20) and [ERC721](https://docs.openzeppelin.com/contracts/erc721). + * Flexible [role-based permissioning](https://docs.openzeppelin.com/contracts/access-control) scheme. + * Reusable [Solidity components](https://docs.openzeppelin.com/contracts/utilities) to build custom contracts and complex decentralized systems. + +:mage: **Not sure how to get started?** Check out [Contracts Wizard](https://wizard.openzeppelin.com/) — an interactive smart contract generator. + +:building_construction: **Want to scale your decentralized application?** Check out [OpenZeppelin Defender](https://openzeppelin.com/defender) — a mission-critical developer security platform to code, audit, deploy, monitor, and operate with confidence. + +> [!IMPORTANT] +> OpenZeppelin Contracts uses semantic versioning to communicate backwards compatibility of its API and storage layout. For upgradeable contracts, the storage layout of different major versions should be assumed incompatible, for example, it is unsafe to upgrade from 4.9.3 to 5.0.0. Learn more at [Backwards Compatibility](https://docs.openzeppelin.com/contracts/backwards-compatibility). + +## Overview + +### Installation + +#### Hardhat (npm) + +``` +$ npm install @openzeppelin/contracts +``` + +#### Foundry (git) + +> [!WARNING] +> When installing via git, it is a common error to use the `master` branch. This is a development branch that should be avoided in favor of tagged releases. The release process involves security measures that the `master` branch does not guarantee. + +> [!WARNING] +> Foundry installs the latest version initially, but subsequent `forge update` commands will use the `master` branch. + +``` +$ forge install OpenZeppelin/openzeppelin-contracts +``` + +Add `@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/` in `remappings.txt.` + +### Usage + +Once installed, you can use the contracts in the library by importing them: + +```solidity +pragma solidity ^0.8.20; + +import {ERC721} from "@openzeppelin/contracts/token/ERC721/ERC721.sol"; + +contract MyCollectible is ERC721 { + constructor() ERC721("MyCollectible", "MCO") { + } +} +``` + +_If you're new to smart contract development, head to [Developing Smart Contracts](https://docs.openzeppelin.com/learn/developing-smart-contracts) to learn about creating a new project and compiling your contracts._ + +To keep your system secure, you should **always** use the installed code as-is, and neither copy-paste it from online sources nor modify it yourself. The library is designed so that only the contracts and functions you use are deployed, so you don't need to worry about it needlessly increasing gas costs. + +## Learn More + +The guides in the [documentation site](https://docs.openzeppelin.com/contracts) will teach about different concepts, and how to use the related contracts that OpenZeppelin Contracts provides: + +* [Access Control](https://docs.openzeppelin.com/contracts/access-control): decide who can perform each of the actions on your system. +* [Tokens](https://docs.openzeppelin.com/contracts/tokens): create tradeable assets or collectives, and distribute them via [Crowdsales](https://docs.openzeppelin.com/contracts/crowdsales). +* [Utilities](https://docs.openzeppelin.com/contracts/utilities): generic useful tools including non-overflowing math, signature verification, and trustless paying systems. + +The [full API](https://docs.openzeppelin.com/contracts/api/token/ERC20) is also thoroughly documented, and serves as a great reference when developing your smart contract application. You can also ask for help or follow Contracts' development in the [community forum](https://forum.openzeppelin.com). + +Finally, you may want to take a look at the [guides on our blog](https://blog.openzeppelin.com/), which cover several common use cases and good practices. The following articles provide great background reading, though please note that some of the referenced tools have changed, as the tooling in the ecosystem continues to rapidly evolve. + +* [The Hitchhiker’s Guide to Smart Contracts in Ethereum](https://blog.openzeppelin.com/the-hitchhikers-guide-to-smart-contracts-in-ethereum-848f08001f05) will help you get an overview of the various tools available for smart contract development, and help you set up your environment. +* [A Gentle Introduction to Ethereum Programming, Part 1](https://blog.openzeppelin.com/a-gentle-introduction-to-ethereum-programming-part-1-783cc7796094) provides very useful information on an introductory level, including many basic concepts from the Ethereum platform. +* For a more in-depth dive, you may read the guide [Designing the Architecture for Your Ethereum Application](https://blog.openzeppelin.com/designing-the-architecture-for-your-ethereum-application-9cec086f8317), which discusses how to better structure your application and its relationship to the real world. + +## Security + +This project is maintained by [OpenZeppelin](https://openzeppelin.com) with the goal of providing a secure and reliable library of smart contract components for the ecosystem. We address security through risk management in various areas such as engineering and open source best practices, scoping and API design, multi-layered review processes, and incident response preparedness. + +The [OpenZeppelin Contracts Security Center](https://contracts.openzeppelin.com/security) contains more details about the secure development process. + +The security policy is detailed in [`SECURITY.md`](./SECURITY.md) as well, and specifies how you can report security vulnerabilities, which versions will receive security patches, and how to stay informed about them. We run a [bug bounty program on Immunefi](https://immunefi.com/bounty/openzeppelin) to reward the responsible disclosure of vulnerabilities. + +The engineering guidelines we follow to promote project quality can be found in [`GUIDELINES.md`](./GUIDELINES.md). + +Past audits can be found in [`audits/`](./audits). + +Smart contracts are a nascent technology and carry a high level of technical risk and uncertainty. Although OpenZeppelin is well known for its security audits, using OpenZeppelin Contracts is not a substitute for a security audit. + +OpenZeppelin Contracts is made available under the MIT License, which disclaims all warranties in relation to the project and which limits the liability of those that contribute and maintain the project, including OpenZeppelin. As set out further in the Terms, you acknowledge that you are solely responsible for any use of OpenZeppelin Contracts and you assume all risks associated with any such use. + +## Contribute + +OpenZeppelin Contracts exists thanks to its contributors. There are many ways you can participate and help build high quality software. Check out the [contribution guide](CONTRIBUTING.md)! + +## License + +OpenZeppelin Contracts is released under the [MIT License](LICENSE). + +## Legal + +Your use of this Project is governed by the terms found at www.openzeppelin.com/tos (the "Terms"). diff --git a/dependencies/@openzeppelin-contracts-5.4.0/access/AccessControl.sol b/dependencies/@openzeppelin-contracts-5.4.0/access/AccessControl.sol new file mode 100644 index 00000000..0c7ec609 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/access/AccessControl.sol @@ -0,0 +1,207 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (access/AccessControl.sol) + +pragma solidity ^0.8.20; + +import {IAccessControl} from "./IAccessControl.sol"; +import {Context} from "../utils/Context.sol"; +import {IERC165, ERC165} from "../utils/introspection/ERC165.sol"; + +/** + * @dev Contract module that allows children to implement role-based access + * control mechanisms. This is a lightweight version that doesn't allow enumerating role + * members except through off-chain means by accessing the contract event logs. Some + * applications may benefit from on-chain enumerability, for those cases see + * {AccessControlEnumerable}. + * + * Roles are referred to by their `bytes32` identifier. These should be exposed + * in the external API and be unique. The best way to achieve this is by + * using `public constant` hash digests: + * + * ```solidity + * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); + * ``` + * + * Roles can be used to represent a set of permissions. To restrict access to a + * function call, use {hasRole}: + * + * ```solidity + * function foo() public { + * require(hasRole(MY_ROLE, msg.sender)); + * ... + * } + * ``` + * + * Roles can be granted and revoked dynamically via the {grantRole} and + * {revokeRole} functions. Each role has an associated admin role, and only + * accounts that have a role's admin role can call {grantRole} and {revokeRole}. + * + * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means + * that only accounts with this role will be able to grant or revoke other + * roles. More complex role relationships can be created by using + * {_setRoleAdmin}. + * + * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to + * grant and revoke this role. Extra precautions should be taken to secure + * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules} + * to enforce additional security measures for this role. + */ +abstract contract AccessControl is Context, IAccessControl, ERC165 { + struct RoleData { + mapping(address account => bool) hasRole; + bytes32 adminRole; + } + + mapping(bytes32 role => RoleData) private _roles; + + bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; + + /** + * @dev Modifier that checks that an account has a specific role. Reverts + * with an {AccessControlUnauthorizedAccount} error including the required role. + */ + modifier onlyRole(bytes32 role) { + _checkRole(role); + _; + } + + /// @inheritdoc IERC165 + function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { + return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); + } + + /** + * @dev Returns `true` if `account` has been granted `role`. + */ + function hasRole(bytes32 role, address account) public view virtual returns (bool) { + return _roles[role].hasRole[account]; + } + + /** + * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()` + * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier. + */ + function _checkRole(bytes32 role) internal view virtual { + _checkRole(role, _msgSender()); + } + + /** + * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account` + * is missing `role`. + */ + function _checkRole(bytes32 role, address account) internal view virtual { + if (!hasRole(role, account)) { + revert AccessControlUnauthorizedAccount(account, role); + } + } + + /** + * @dev Returns the admin role that controls `role`. See {grantRole} and + * {revokeRole}. + * + * To change a role's admin, use {_setRoleAdmin}. + */ + function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) { + return _roles[role].adminRole; + } + + /** + * @dev Grants `role` to `account`. + * + * If `account` had not been already granted `role`, emits a {RoleGranted} + * event. + * + * Requirements: + * + * - the caller must have ``role``'s admin role. + * + * May emit a {RoleGranted} event. + */ + function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) { + _grantRole(role, account); + } + + /** + * @dev Revokes `role` from `account`. + * + * If `account` had been granted `role`, emits a {RoleRevoked} event. + * + * Requirements: + * + * - the caller must have ``role``'s admin role. + * + * May emit a {RoleRevoked} event. + */ + function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) { + _revokeRole(role, account); + } + + /** + * @dev Revokes `role` from the calling account. + * + * Roles are often managed via {grantRole} and {revokeRole}: this function's + * purpose is to provide a mechanism for accounts to lose their privileges + * if they are compromised (such as when a trusted device is misplaced). + * + * If the calling account had been revoked `role`, emits a {RoleRevoked} + * event. + * + * Requirements: + * + * - the caller must be `callerConfirmation`. + * + * May emit a {RoleRevoked} event. + */ + function renounceRole(bytes32 role, address callerConfirmation) public virtual { + if (callerConfirmation != _msgSender()) { + revert AccessControlBadConfirmation(); + } + + _revokeRole(role, callerConfirmation); + } + + /** + * @dev Sets `adminRole` as ``role``'s admin role. + * + * Emits a {RoleAdminChanged} event. + */ + function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { + bytes32 previousAdminRole = getRoleAdmin(role); + _roles[role].adminRole = adminRole; + emit RoleAdminChanged(role, previousAdminRole, adminRole); + } + + /** + * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted. + * + * Internal function without access restriction. + * + * May emit a {RoleGranted} event. + */ + function _grantRole(bytes32 role, address account) internal virtual returns (bool) { + if (!hasRole(role, account)) { + _roles[role].hasRole[account] = true; + emit RoleGranted(role, account, _msgSender()); + return true; + } else { + return false; + } + } + + /** + * @dev Attempts to revoke `role` from `account` and returns a boolean indicating if `role` was revoked. + * + * Internal function without access restriction. + * + * May emit a {RoleRevoked} event. + */ + function _revokeRole(bytes32 role, address account) internal virtual returns (bool) { + if (hasRole(role, account)) { + _roles[role].hasRole[account] = false; + emit RoleRevoked(role, account, _msgSender()); + return true; + } else { + return false; + } + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/access/IAccessControl.sol b/dependencies/@openzeppelin-contracts-5.4.0/access/IAccessControl.sol new file mode 100644 index 00000000..23f0770a --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/access/IAccessControl.sol @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (access/IAccessControl.sol) + +pragma solidity >=0.8.4; + +/** + * @dev External interface of AccessControl declared to support ERC-165 detection. + */ +interface IAccessControl { + /** + * @dev The `account` is missing a role. + */ + error AccessControlUnauthorizedAccount(address account, bytes32 neededRole); + + /** + * @dev The caller of a function is not the expected one. + * + * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}. + */ + error AccessControlBadConfirmation(); + + /** + * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` + * + * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite + * {RoleAdminChanged} not being emitted to signal this. + */ + event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); + + /** + * @dev Emitted when `account` is granted `role`. + * + * `sender` is the account that originated the contract call. This account bears the admin role (for the granted role). + * Expected in cases where the role was granted using the internal {AccessControl-_grantRole}. + */ + event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); + + /** + * @dev Emitted when `account` is revoked `role`. + * + * `sender` is the account that originated the contract call: + * - if using `revokeRole`, it is the admin role bearer + * - if using `renounceRole`, it is the role bearer (i.e. `account`) + */ + event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); + + /** + * @dev Returns `true` if `account` has been granted `role`. + */ + function hasRole(bytes32 role, address account) external view returns (bool); + + /** + * @dev Returns the admin role that controls `role`. See {grantRole} and + * {revokeRole}. + * + * To change a role's admin, use {AccessControl-_setRoleAdmin}. + */ + function getRoleAdmin(bytes32 role) external view returns (bytes32); + + /** + * @dev Grants `role` to `account`. + * + * If `account` had not been already granted `role`, emits a {RoleGranted} + * event. + * + * Requirements: + * + * - the caller must have ``role``'s admin role. + */ + function grantRole(bytes32 role, address account) external; + + /** + * @dev Revokes `role` from `account`. + * + * If `account` had been granted `role`, emits a {RoleRevoked} event. + * + * Requirements: + * + * - the caller must have ``role``'s admin role. + */ + function revokeRole(bytes32 role, address account) external; + + /** + * @dev Revokes `role` from the calling account. + * + * Roles are often managed via {grantRole} and {revokeRole}: this function's + * purpose is to provide a mechanism for accounts to lose their privileges + * if they are compromised (such as when a trusted device is misplaced). + * + * If the calling account had been granted `role`, emits a {RoleRevoked} + * event. + * + * Requirements: + * + * - the caller must be `callerConfirmation`. + */ + function renounceRole(bytes32 role, address callerConfirmation) external; +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/access/Ownable.sol b/dependencies/@openzeppelin-contracts-5.4.0/access/Ownable.sol new file mode 100644 index 00000000..bd96f666 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/access/Ownable.sol @@ -0,0 +1,100 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) + +pragma solidity ^0.8.20; + +import {Context} from "../utils/Context.sol"; + +/** + * @dev Contract module which provides a basic access control mechanism, where + * there is an account (an owner) that can be granted exclusive access to + * specific functions. + * + * The initial owner is set to the address provided by the deployer. This can + * later be changed with {transferOwnership}. + * + * This module is used through inheritance. It will make available the modifier + * `onlyOwner`, which can be applied to your functions to restrict their use to + * the owner. + */ +abstract contract Ownable is Context { + address private _owner; + + /** + * @dev The caller account is not authorized to perform an operation. + */ + error OwnableUnauthorizedAccount(address account); + + /** + * @dev The owner is not a valid owner account. (eg. `address(0)`) + */ + error OwnableInvalidOwner(address owner); + + event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); + + /** + * @dev Initializes the contract setting the address provided by the deployer as the initial owner. + */ + constructor(address initialOwner) { + if (initialOwner == address(0)) { + revert OwnableInvalidOwner(address(0)); + } + _transferOwnership(initialOwner); + } + + /** + * @dev Throws if called by any account other than the owner. + */ + modifier onlyOwner() { + _checkOwner(); + _; + } + + /** + * @dev Returns the address of the current owner. + */ + function owner() public view virtual returns (address) { + return _owner; + } + + /** + * @dev Throws if the sender is not the owner. + */ + function _checkOwner() internal view virtual { + if (owner() != _msgSender()) { + revert OwnableUnauthorizedAccount(_msgSender()); + } + } + + /** + * @dev Leaves the contract without owner. It will not be possible to call + * `onlyOwner` functions. Can only be called by the current owner. + * + * NOTE: Renouncing ownership will leave the contract without an owner, + * thereby disabling any functionality that is only available to the owner. + */ + function renounceOwnership() public virtual onlyOwner { + _transferOwnership(address(0)); + } + + /** + * @dev Transfers ownership of the contract to a new account (`newOwner`). + * Can only be called by the current owner. + */ + function transferOwnership(address newOwner) public virtual onlyOwner { + if (newOwner == address(0)) { + revert OwnableInvalidOwner(address(0)); + } + _transferOwnership(newOwner); + } + + /** + * @dev Transfers ownership of the contract to a new account (`newOwner`). + * Internal function without access restriction. + */ + function _transferOwnership(address newOwner) internal virtual { + address oldOwner = _owner; + _owner = newOwner; + emit OwnershipTransferred(oldOwner, newOwner); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/access/Ownable2Step.sol b/dependencies/@openzeppelin-contracts-5.4.0/access/Ownable2Step.sol new file mode 100644 index 00000000..3a0747ce --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/access/Ownable2Step.sol @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.1.0) (access/Ownable2Step.sol) + +pragma solidity ^0.8.20; + +import {Ownable} from "./Ownable.sol"; + +/** + * @dev Contract module which provides access control mechanism, where + * there is an account (an owner) that can be granted exclusive access to + * specific functions. + * + * This extension of the {Ownable} contract includes a two-step mechanism to transfer + * ownership, where the new owner must call {acceptOwnership} in order to replace the + * old one. This can help prevent common mistakes, such as transfers of ownership to + * incorrect accounts, or to contracts that are unable to interact with the + * permission system. + * + * The initial owner is specified at deployment time in the constructor for `Ownable`. This + * can later be changed with {transferOwnership} and {acceptOwnership}. + * + * This module is used through inheritance. It will make available all functions + * from parent (Ownable). + */ +abstract contract Ownable2Step is Ownable { + address private _pendingOwner; + + event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner); + + /** + * @dev Returns the address of the pending owner. + */ + function pendingOwner() public view virtual returns (address) { + return _pendingOwner; + } + + /** + * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. + * Can only be called by the current owner. + * + * Setting `newOwner` to the zero address is allowed; this can be used to cancel an initiated ownership transfer. + */ + function transferOwnership(address newOwner) public virtual override onlyOwner { + _pendingOwner = newOwner; + emit OwnershipTransferStarted(owner(), newOwner); + } + + /** + * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner. + * Internal function without access restriction. + */ + function _transferOwnership(address newOwner) internal virtual override { + delete _pendingOwner; + super._transferOwnership(newOwner); + } + + /** + * @dev The new owner accepts the ownership transfer. + */ + function acceptOwnership() public virtual { + address sender = _msgSender(); + if (pendingOwner() != sender) { + revert OwnableUnauthorizedAccount(sender); + } + _transferOwnership(sender); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/access/extensions/AccessControlDefaultAdminRules.sol b/dependencies/@openzeppelin-contracts-5.4.0/access/extensions/AccessControlDefaultAdminRules.sol new file mode 100644 index 00000000..77a7e45b --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/access/extensions/AccessControlDefaultAdminRules.sol @@ -0,0 +1,372 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (access/extensions/AccessControlDefaultAdminRules.sol) + +pragma solidity ^0.8.20; + +import {IAccessControlDefaultAdminRules} from "./IAccessControlDefaultAdminRules.sol"; +import {AccessControl, IAccessControl} from "../AccessControl.sol"; +import {SafeCast} from "../../utils/math/SafeCast.sol"; +import {Math} from "../../utils/math/Math.sol"; +import {IERC5313} from "../../interfaces/IERC5313.sol"; +import {IERC165} from "../../utils/introspection/ERC165.sol"; + +/** + * @dev Extension of {AccessControl} that allows specifying special rules to manage + * the `DEFAULT_ADMIN_ROLE` holder, which is a sensitive role with special permissions + * over other roles that may potentially have privileged rights in the system. + * + * If a specific role doesn't have an admin role assigned, the holder of the + * `DEFAULT_ADMIN_ROLE` will have the ability to grant it and revoke it. + * + * This contract implements the following risk mitigations on top of {AccessControl}: + * + * * Only one account holds the `DEFAULT_ADMIN_ROLE` since deployment until it's potentially renounced. + * * Enforces a 2-step process to transfer the `DEFAULT_ADMIN_ROLE` to another account. + * * Enforces a configurable delay between the two steps, with the ability to cancel before the transfer is accepted. + * * The delay can be changed by scheduling, see {changeDefaultAdminDelay}. + * * Role transfers must wait at least one block after scheduling before it can be accepted. + * * It is not possible to use another role to manage the `DEFAULT_ADMIN_ROLE`. + * + * Example usage: + * + * ```solidity + * contract MyToken is AccessControlDefaultAdminRules { + * constructor() AccessControlDefaultAdminRules( + * 3 days, + * msg.sender // Explicit initial `DEFAULT_ADMIN_ROLE` holder + * ) {} + * } + * ``` + */ +abstract contract AccessControlDefaultAdminRules is IAccessControlDefaultAdminRules, IERC5313, AccessControl { + // pending admin pair read/written together frequently + address private _pendingDefaultAdmin; + uint48 private _pendingDefaultAdminSchedule; // 0 == unset + + uint48 private _currentDelay; + address private _currentDefaultAdmin; + + // pending delay pair read/written together frequently + uint48 private _pendingDelay; + uint48 private _pendingDelaySchedule; // 0 == unset + + /** + * @dev Sets the initial values for {defaultAdminDelay} and {defaultAdmin} address. + */ + constructor(uint48 initialDelay, address initialDefaultAdmin) { + if (initialDefaultAdmin == address(0)) { + revert AccessControlInvalidDefaultAdmin(address(0)); + } + _currentDelay = initialDelay; + _grantRole(DEFAULT_ADMIN_ROLE, initialDefaultAdmin); + } + + /// @inheritdoc IERC165 + function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { + return interfaceId == type(IAccessControlDefaultAdminRules).interfaceId || super.supportsInterface(interfaceId); + } + + /// @inheritdoc IERC5313 + function owner() public view virtual returns (address) { + return defaultAdmin(); + } + + /// + /// Override AccessControl role management + /// + + /** + * @dev See {AccessControl-grantRole}. Reverts for `DEFAULT_ADMIN_ROLE`. + */ + function grantRole(bytes32 role, address account) public virtual override(AccessControl, IAccessControl) { + if (role == DEFAULT_ADMIN_ROLE) { + revert AccessControlEnforcedDefaultAdminRules(); + } + super.grantRole(role, account); + } + + /** + * @dev See {AccessControl-revokeRole}. Reverts for `DEFAULT_ADMIN_ROLE`. + */ + function revokeRole(bytes32 role, address account) public virtual override(AccessControl, IAccessControl) { + if (role == DEFAULT_ADMIN_ROLE) { + revert AccessControlEnforcedDefaultAdminRules(); + } + super.revokeRole(role, account); + } + + /** + * @dev See {AccessControl-renounceRole}. + * + * For the `DEFAULT_ADMIN_ROLE`, it only allows renouncing in two steps by first calling + * {beginDefaultAdminTransfer} to the `address(0)`, so it's required that the {pendingDefaultAdmin} schedule + * has also passed when calling this function. + * + * After its execution, it will not be possible to call `onlyRole(DEFAULT_ADMIN_ROLE)` functions. + * + * NOTE: Renouncing `DEFAULT_ADMIN_ROLE` will leave the contract without a {defaultAdmin}, + * thereby disabling any functionality that is only available for it, and the possibility of reassigning a + * non-administrated role. + */ + function renounceRole(bytes32 role, address account) public virtual override(AccessControl, IAccessControl) { + if (role == DEFAULT_ADMIN_ROLE && account == defaultAdmin()) { + (address newDefaultAdmin, uint48 schedule) = pendingDefaultAdmin(); + if (newDefaultAdmin != address(0) || !_isScheduleSet(schedule) || !_hasSchedulePassed(schedule)) { + revert AccessControlEnforcedDefaultAdminDelay(schedule); + } + delete _pendingDefaultAdminSchedule; + } + super.renounceRole(role, account); + } + + /** + * @dev See {AccessControl-_grantRole}. + * + * For `DEFAULT_ADMIN_ROLE`, it only allows granting if there isn't already a {defaultAdmin} or if the + * role has been previously renounced. + * + * NOTE: Exposing this function through another mechanism may make the `DEFAULT_ADMIN_ROLE` + * assignable again. Make sure to guarantee this is the expected behavior in your implementation. + */ + function _grantRole(bytes32 role, address account) internal virtual override returns (bool) { + if (role == DEFAULT_ADMIN_ROLE) { + if (defaultAdmin() != address(0)) { + revert AccessControlEnforcedDefaultAdminRules(); + } + _currentDefaultAdmin = account; + } + return super._grantRole(role, account); + } + + /// @inheritdoc AccessControl + function _revokeRole(bytes32 role, address account) internal virtual override returns (bool) { + if (role == DEFAULT_ADMIN_ROLE && account == defaultAdmin()) { + delete _currentDefaultAdmin; + } + return super._revokeRole(role, account); + } + + /** + * @dev See {AccessControl-_setRoleAdmin}. Reverts for `DEFAULT_ADMIN_ROLE`. + */ + function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual override { + if (role == DEFAULT_ADMIN_ROLE) { + revert AccessControlEnforcedDefaultAdminRules(); + } + super._setRoleAdmin(role, adminRole); + } + + /// + /// AccessControlDefaultAdminRules accessors + /// + + /// @inheritdoc IAccessControlDefaultAdminRules + function defaultAdmin() public view virtual returns (address) { + return _currentDefaultAdmin; + } + + /// @inheritdoc IAccessControlDefaultAdminRules + function pendingDefaultAdmin() public view virtual returns (address newAdmin, uint48 schedule) { + return (_pendingDefaultAdmin, _pendingDefaultAdminSchedule); + } + + /// @inheritdoc IAccessControlDefaultAdminRules + function defaultAdminDelay() public view virtual returns (uint48) { + uint48 schedule = _pendingDelaySchedule; + return (_isScheduleSet(schedule) && _hasSchedulePassed(schedule)) ? _pendingDelay : _currentDelay; + } + + /// @inheritdoc IAccessControlDefaultAdminRules + function pendingDefaultAdminDelay() public view virtual returns (uint48 newDelay, uint48 schedule) { + schedule = _pendingDelaySchedule; + return (_isScheduleSet(schedule) && !_hasSchedulePassed(schedule)) ? (_pendingDelay, schedule) : (0, 0); + } + + /// @inheritdoc IAccessControlDefaultAdminRules + function defaultAdminDelayIncreaseWait() public view virtual returns (uint48) { + return 5 days; + } + + /// + /// AccessControlDefaultAdminRules public and internal setters for defaultAdmin/pendingDefaultAdmin + /// + + /// @inheritdoc IAccessControlDefaultAdminRules + function beginDefaultAdminTransfer(address newAdmin) public virtual onlyRole(DEFAULT_ADMIN_ROLE) { + _beginDefaultAdminTransfer(newAdmin); + } + + /** + * @dev See {beginDefaultAdminTransfer}. + * + * Internal function without access restriction. + */ + function _beginDefaultAdminTransfer(address newAdmin) internal virtual { + uint48 newSchedule = SafeCast.toUint48(block.timestamp) + defaultAdminDelay(); + _setPendingDefaultAdmin(newAdmin, newSchedule); + emit DefaultAdminTransferScheduled(newAdmin, newSchedule); + } + + /// @inheritdoc IAccessControlDefaultAdminRules + function cancelDefaultAdminTransfer() public virtual onlyRole(DEFAULT_ADMIN_ROLE) { + _cancelDefaultAdminTransfer(); + } + + /** + * @dev See {cancelDefaultAdminTransfer}. + * + * Internal function without access restriction. + */ + function _cancelDefaultAdminTransfer() internal virtual { + _setPendingDefaultAdmin(address(0), 0); + } + + /// @inheritdoc IAccessControlDefaultAdminRules + function acceptDefaultAdminTransfer() public virtual { + (address newDefaultAdmin, ) = pendingDefaultAdmin(); + if (_msgSender() != newDefaultAdmin) { + // Enforce newDefaultAdmin explicit acceptance. + revert AccessControlInvalidDefaultAdmin(_msgSender()); + } + _acceptDefaultAdminTransfer(); + } + + /** + * @dev See {acceptDefaultAdminTransfer}. + * + * Internal function without access restriction. + */ + function _acceptDefaultAdminTransfer() internal virtual { + (address newAdmin, uint48 schedule) = pendingDefaultAdmin(); + if (!_isScheduleSet(schedule) || !_hasSchedulePassed(schedule)) { + revert AccessControlEnforcedDefaultAdminDelay(schedule); + } + _revokeRole(DEFAULT_ADMIN_ROLE, defaultAdmin()); + _grantRole(DEFAULT_ADMIN_ROLE, newAdmin); + delete _pendingDefaultAdmin; + delete _pendingDefaultAdminSchedule; + } + + /// + /// AccessControlDefaultAdminRules public and internal setters for defaultAdminDelay/pendingDefaultAdminDelay + /// + + /// @inheritdoc IAccessControlDefaultAdminRules + function changeDefaultAdminDelay(uint48 newDelay) public virtual onlyRole(DEFAULT_ADMIN_ROLE) { + _changeDefaultAdminDelay(newDelay); + } + + /** + * @dev See {changeDefaultAdminDelay}. + * + * Internal function without access restriction. + */ + function _changeDefaultAdminDelay(uint48 newDelay) internal virtual { + uint48 newSchedule = SafeCast.toUint48(block.timestamp) + _delayChangeWait(newDelay); + _setPendingDelay(newDelay, newSchedule); + emit DefaultAdminDelayChangeScheduled(newDelay, newSchedule); + } + + /// @inheritdoc IAccessControlDefaultAdminRules + function rollbackDefaultAdminDelay() public virtual onlyRole(DEFAULT_ADMIN_ROLE) { + _rollbackDefaultAdminDelay(); + } + + /** + * @dev See {rollbackDefaultAdminDelay}. + * + * Internal function without access restriction. + */ + function _rollbackDefaultAdminDelay() internal virtual { + _setPendingDelay(0, 0); + } + + /** + * @dev Returns the amount of seconds to wait after the `newDelay` will + * become the new {defaultAdminDelay}. + * + * The value returned guarantees that if the delay is reduced, it will go into effect + * after a wait that honors the previously set delay. + * + * See {defaultAdminDelayIncreaseWait}. + */ + function _delayChangeWait(uint48 newDelay) internal view virtual returns (uint48) { + uint48 currentDelay = defaultAdminDelay(); + + // When increasing the delay, we schedule the delay change to occur after a period of "new delay" has passed, up + // to a maximum given by defaultAdminDelayIncreaseWait, by default 5 days. For example, if increasing from 1 day + // to 3 days, the new delay will come into effect after 3 days. If increasing from 1 day to 10 days, the new + // delay will come into effect after 5 days. The 5 day wait period is intended to be able to fix an error like + // using milliseconds instead of seconds. + // + // When decreasing the delay, we wait the difference between "current delay" and "new delay". This guarantees + // that an admin transfer cannot be made faster than "current delay" at the time the delay change is scheduled. + // For example, if decreasing from 10 days to 3 days, the new delay will come into effect after 7 days. + return + newDelay > currentDelay + ? uint48(Math.min(newDelay, defaultAdminDelayIncreaseWait())) // no need to safecast, both inputs are uint48 + : currentDelay - newDelay; + } + + /// + /// Private setters + /// + + /** + * @dev Setter of the tuple for pending admin and its schedule. + * + * May emit a DefaultAdminTransferCanceled event. + */ + function _setPendingDefaultAdmin(address newAdmin, uint48 newSchedule) private { + (, uint48 oldSchedule) = pendingDefaultAdmin(); + + _pendingDefaultAdmin = newAdmin; + _pendingDefaultAdminSchedule = newSchedule; + + // An `oldSchedule` from `pendingDefaultAdmin()` is only set if it hasn't been accepted. + if (_isScheduleSet(oldSchedule)) { + // Emit for implicit cancellations when another default admin was scheduled. + emit DefaultAdminTransferCanceled(); + } + } + + /** + * @dev Setter of the tuple for pending delay and its schedule. + * + * May emit a DefaultAdminDelayChangeCanceled event. + */ + function _setPendingDelay(uint48 newDelay, uint48 newSchedule) private { + uint48 oldSchedule = _pendingDelaySchedule; + + if (_isScheduleSet(oldSchedule)) { + if (_hasSchedulePassed(oldSchedule)) { + // Materialize a virtual delay + _currentDelay = _pendingDelay; + } else { + // Emit for implicit cancellations when another delay was scheduled. + emit DefaultAdminDelayChangeCanceled(); + } + } + + _pendingDelay = newDelay; + _pendingDelaySchedule = newSchedule; + } + + /// + /// Private helpers + /// + + /** + * @dev Defines if an `schedule` is considered set. For consistency purposes. + */ + function _isScheduleSet(uint48 schedule) private pure returns (bool) { + return schedule != 0; + } + + /** + * @dev Defines if an `schedule` is considered passed. For consistency purposes. + */ + function _hasSchedulePassed(uint48 schedule) private view returns (bool) { + return schedule < block.timestamp; + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/access/extensions/AccessControlEnumerable.sol b/dependencies/@openzeppelin-contracts-5.4.0/access/extensions/AccessControlEnumerable.sol new file mode 100644 index 00000000..f2d79fd5 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/access/extensions/AccessControlEnumerable.sol @@ -0,0 +1,81 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (access/extensions/AccessControlEnumerable.sol) + +pragma solidity ^0.8.20; + +import {IAccessControlEnumerable} from "./IAccessControlEnumerable.sol"; +import {AccessControl} from "../AccessControl.sol"; +import {EnumerableSet} from "../../utils/structs/EnumerableSet.sol"; +import {IERC165} from "../../utils/introspection/ERC165.sol"; + +/** + * @dev Extension of {AccessControl} that allows enumerating the members of each role. + */ +abstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl { + using EnumerableSet for EnumerableSet.AddressSet; + + mapping(bytes32 role => EnumerableSet.AddressSet) private _roleMembers; + + /// @inheritdoc IERC165 + function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { + return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId); + } + + /** + * @dev Returns one of the accounts that have `role`. `index` must be a + * value between 0 and {getRoleMemberCount}, non-inclusive. + * + * Role bearers are not sorted in any particular way, and their ordering may + * change at any point. + * + * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure + * you perform all queries on the same block. See the following + * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] + * for more information. + */ + function getRoleMember(bytes32 role, uint256 index) public view virtual returns (address) { + return _roleMembers[role].at(index); + } + + /** + * @dev Returns the number of accounts that have `role`. Can be used + * together with {getRoleMember} to enumerate all bearers of a role. + */ + function getRoleMemberCount(bytes32 role) public view virtual returns (uint256) { + return _roleMembers[role].length(); + } + + /** + * @dev Return all accounts that have `role` + * + * 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 getRoleMembers(bytes32 role) public view virtual returns (address[] memory) { + return _roleMembers[role].values(); + } + + /** + * @dev Overload {AccessControl-_grantRole} to track enumerable memberships + */ + function _grantRole(bytes32 role, address account) internal virtual override returns (bool) { + bool granted = super._grantRole(role, account); + if (granted) { + _roleMembers[role].add(account); + } + return granted; + } + + /** + * @dev Overload {AccessControl-_revokeRole} to track enumerable memberships + */ + function _revokeRole(bytes32 role, address account) internal virtual override returns (bool) { + bool revoked = super._revokeRole(role, account); + if (revoked) { + _roleMembers[role].remove(account); + } + return revoked; + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/access/extensions/IAccessControlDefaultAdminRules.sol b/dependencies/@openzeppelin-contracts-5.4.0/access/extensions/IAccessControlDefaultAdminRules.sol new file mode 100644 index 00000000..616b4d8a --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/access/extensions/IAccessControlDefaultAdminRules.sol @@ -0,0 +1,192 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (access/extensions/IAccessControlDefaultAdminRules.sol) + +pragma solidity >=0.8.4; + +import {IAccessControl} from "../IAccessControl.sol"; + +/** + * @dev External interface of AccessControlDefaultAdminRules declared to support ERC-165 detection. + */ +interface IAccessControlDefaultAdminRules is IAccessControl { + /** + * @dev The new default admin is not a valid default admin. + */ + error AccessControlInvalidDefaultAdmin(address defaultAdmin); + + /** + * @dev At least one of the following rules was violated: + * + * - The `DEFAULT_ADMIN_ROLE` must only be managed by itself. + * - The `DEFAULT_ADMIN_ROLE` must only be held by one account at the time. + * - Any `DEFAULT_ADMIN_ROLE` transfer must be in two delayed steps. + */ + error AccessControlEnforcedDefaultAdminRules(); + + /** + * @dev The delay for transferring the default admin delay is enforced and + * the operation must wait until `schedule`. + * + * NOTE: `schedule` can be 0 indicating there's no transfer scheduled. + */ + error AccessControlEnforcedDefaultAdminDelay(uint48 schedule); + + /** + * @dev Emitted when a {defaultAdmin} transfer is started, setting `newAdmin` as the next + * address to become the {defaultAdmin} by calling {acceptDefaultAdminTransfer} only after `acceptSchedule` + * passes. + */ + event DefaultAdminTransferScheduled(address indexed newAdmin, uint48 acceptSchedule); + + /** + * @dev Emitted when a {pendingDefaultAdmin} is reset if it was never accepted, regardless of its schedule. + */ + event DefaultAdminTransferCanceled(); + + /** + * @dev Emitted when a {defaultAdminDelay} change is started, setting `newDelay` as the next + * delay to be applied between default admin transfer after `effectSchedule` has passed. + */ + event DefaultAdminDelayChangeScheduled(uint48 newDelay, uint48 effectSchedule); + + /** + * @dev Emitted when a {pendingDefaultAdminDelay} is reset if its schedule didn't pass. + */ + event DefaultAdminDelayChangeCanceled(); + + /** + * @dev Returns the address of the current `DEFAULT_ADMIN_ROLE` holder. + */ + function defaultAdmin() external view returns (address); + + /** + * @dev Returns a tuple of a `newAdmin` and an accept schedule. + * + * After the `schedule` passes, the `newAdmin` will be able to accept the {defaultAdmin} role + * by calling {acceptDefaultAdminTransfer}, completing the role transfer. + * + * A zero value only in `acceptSchedule` indicates no pending admin transfer. + * + * NOTE: A zero address `newAdmin` means that {defaultAdmin} is being renounced. + */ + function pendingDefaultAdmin() external view returns (address newAdmin, uint48 acceptSchedule); + + /** + * @dev Returns the delay required to schedule the acceptance of a {defaultAdmin} transfer started. + * + * This delay will be added to the current timestamp when calling {beginDefaultAdminTransfer} to set + * the acceptance schedule. + * + * NOTE: If a delay change has been scheduled, it will take effect as soon as the schedule passes, making this + * function returns the new delay. See {changeDefaultAdminDelay}. + */ + function defaultAdminDelay() external view returns (uint48); + + /** + * @dev Returns a tuple of `newDelay` and an effect schedule. + * + * After the `schedule` passes, the `newDelay` will get into effect immediately for every + * new {defaultAdmin} transfer started with {beginDefaultAdminTransfer}. + * + * A zero value only in `effectSchedule` indicates no pending delay change. + * + * NOTE: A zero value only for `newDelay` means that the next {defaultAdminDelay} + * will be zero after the effect schedule. + */ + function pendingDefaultAdminDelay() external view returns (uint48 newDelay, uint48 effectSchedule); + + /** + * @dev Starts a {defaultAdmin} transfer by setting a {pendingDefaultAdmin} scheduled for acceptance + * after the current timestamp plus a {defaultAdminDelay}. + * + * Requirements: + * + * - Only can be called by the current {defaultAdmin}. + * + * Emits a DefaultAdminRoleChangeStarted event. + */ + function beginDefaultAdminTransfer(address newAdmin) external; + + /** + * @dev Cancels a {defaultAdmin} transfer previously started with {beginDefaultAdminTransfer}. + * + * A {pendingDefaultAdmin} not yet accepted can also be cancelled with this function. + * + * Requirements: + * + * - Only can be called by the current {defaultAdmin}. + * + * May emit a DefaultAdminTransferCanceled event. + */ + function cancelDefaultAdminTransfer() external; + + /** + * @dev Completes a {defaultAdmin} transfer previously started with {beginDefaultAdminTransfer}. + * + * After calling the function: + * + * - `DEFAULT_ADMIN_ROLE` should be granted to the caller. + * - `DEFAULT_ADMIN_ROLE` should be revoked from the previous holder. + * - {pendingDefaultAdmin} should be reset to zero values. + * + * Requirements: + * + * - Only can be called by the {pendingDefaultAdmin}'s `newAdmin`. + * - The {pendingDefaultAdmin}'s `acceptSchedule` should've passed. + */ + function acceptDefaultAdminTransfer() external; + + /** + * @dev Initiates a {defaultAdminDelay} update by setting a {pendingDefaultAdminDelay} scheduled for getting + * into effect after the current timestamp plus a {defaultAdminDelay}. + * + * This function guarantees that any call to {beginDefaultAdminTransfer} done between the timestamp this + * method is called and the {pendingDefaultAdminDelay} effect schedule will use the current {defaultAdminDelay} + * set before calling. + * + * The {pendingDefaultAdminDelay}'s effect schedule is defined in a way that waiting until the schedule and then + * calling {beginDefaultAdminTransfer} with the new delay will take at least the same as another {defaultAdmin} + * complete transfer (including acceptance). + * + * The schedule is designed for two scenarios: + * + * - When the delay is changed for a larger one the schedule is `block.timestamp + newDelay` capped by + * {defaultAdminDelayIncreaseWait}. + * - When the delay is changed for a shorter one, the schedule is `block.timestamp + (current delay - new delay)`. + * + * A {pendingDefaultAdminDelay} that never got into effect will be canceled in favor of a new scheduled change. + * + * Requirements: + * + * - Only can be called by the current {defaultAdmin}. + * + * Emits a DefaultAdminDelayChangeScheduled event and may emit a DefaultAdminDelayChangeCanceled event. + */ + function changeDefaultAdminDelay(uint48 newDelay) external; + + /** + * @dev Cancels a scheduled {defaultAdminDelay} change. + * + * Requirements: + * + * - Only can be called by the current {defaultAdmin}. + * + * May emit a DefaultAdminDelayChangeCanceled event. + */ + function rollbackDefaultAdminDelay() external; + + /** + * @dev Maximum time in seconds for an increase to {defaultAdminDelay} (that is scheduled using {changeDefaultAdminDelay}) + * to take effect. Default to 5 days. + * + * When the {defaultAdminDelay} is scheduled to be increased, it goes into effect after the new delay has passed with + * the purpose of giving enough time for reverting any accidental change (i.e. using milliseconds instead of seconds) + * that may lock the contract. However, to avoid excessive schedules, the wait is capped by this function and it can + * be overrode for a custom {defaultAdminDelay} increase scheduling. + * + * IMPORTANT: Make sure to add a reasonable amount of time while overriding this value, otherwise, + * there's a risk of setting a high new delay that goes into effect almost immediately without the + * possibility of human intervention in the case of an input error (eg. set milliseconds instead of seconds). + */ + function defaultAdminDelayIncreaseWait() external view returns (uint48); +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/access/extensions/IAccessControlEnumerable.sol b/dependencies/@openzeppelin-contracts-5.4.0/access/extensions/IAccessControlEnumerable.sol new file mode 100644 index 00000000..90371fa9 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/access/extensions/IAccessControlEnumerable.sol @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (access/extensions/IAccessControlEnumerable.sol) + +pragma solidity >=0.8.4; + +import {IAccessControl} from "../IAccessControl.sol"; + +/** + * @dev External interface of AccessControlEnumerable declared to support ERC-165 detection. + */ +interface IAccessControlEnumerable is IAccessControl { + /** + * @dev Returns one of the accounts that have `role`. `index` must be a + * value between 0 and {getRoleMemberCount}, non-inclusive. + * + * Role bearers are not sorted in any particular way, and their ordering may + * change at any point. + * + * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure + * you perform all queries on the same block. See the following + * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] + * for more information. + */ + function getRoleMember(bytes32 role, uint256 index) external view returns (address); + + /** + * @dev Returns the number of accounts that have `role`. Can be used + * together with {getRoleMember} to enumerate all bearers of a role. + */ + function getRoleMemberCount(bytes32 role) external view returns (uint256); +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/access/manager/AccessManaged.sol b/dependencies/@openzeppelin-contracts-5.4.0/access/manager/AccessManaged.sol new file mode 100644 index 00000000..382a3086 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/access/manager/AccessManaged.sol @@ -0,0 +1,112 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (access/manager/AccessManaged.sol) + +pragma solidity ^0.8.20; + +import {AuthorityUtils} from "./AuthorityUtils.sol"; +import {IAccessManager} from "./IAccessManager.sol"; +import {IAccessManaged} from "./IAccessManaged.sol"; +import {Context} from "../../utils/Context.sol"; + +/** + * @dev This contract module makes available a {restricted} modifier. Functions decorated with this modifier will be + * permissioned according to an "authority": a contract like {AccessManager} that follows the {IAuthority} interface, + * implementing a policy that allows certain callers to access certain functions. + * + * IMPORTANT: The `restricted` modifier should never be used on `internal` functions, judiciously used in `public` + * functions, and ideally only used in `external` functions. See {restricted}. + */ +abstract contract AccessManaged is Context, IAccessManaged { + address private _authority; + + bool private _consumingSchedule; + + /** + * @dev Initializes the contract connected to an initial authority. + */ + constructor(address initialAuthority) { + _setAuthority(initialAuthority); + } + + /** + * @dev Restricts access to a function as defined by the connected Authority for this contract and the + * caller and selector of the function that entered the contract. + * + * [IMPORTANT] + * ==== + * In general, this modifier should only be used on `external` functions. It is okay to use it on `public` + * functions that are used as external entry points and are not called internally. Unless you know what you're + * doing, it should never be used on `internal` functions. Failure to follow these rules can have critical security + * implications! This is because the permissions are determined by the function that entered the contract, i.e. the + * function at the bottom of the call stack, and not the function where the modifier is visible in the source code. + * ==== + * + * [WARNING] + * ==== + * Avoid adding this modifier to the https://docs.soliditylang.org/en/v0.8.20/contracts.html#receive-ether-function[`receive()`] + * function or the https://docs.soliditylang.org/en/v0.8.20/contracts.html#fallback-function[`fallback()`]. These + * functions are the only execution paths where a function selector cannot be unambiguously determined from the calldata + * since the selector defaults to `0x00000000` in the `receive()` function and similarly in the `fallback()` function + * if no calldata is provided. (See {_checkCanCall}). + * + * The `receive()` function will always panic whereas the `fallback()` may panic depending on the calldata length. + * ==== + */ + modifier restricted() { + _checkCanCall(_msgSender(), _msgData()); + _; + } + + /// @inheritdoc IAccessManaged + function authority() public view virtual returns (address) { + return _authority; + } + + /// @inheritdoc IAccessManaged + function setAuthority(address newAuthority) public virtual { + address caller = _msgSender(); + if (caller != authority()) { + revert AccessManagedUnauthorized(caller); + } + if (newAuthority.code.length == 0) { + revert AccessManagedInvalidAuthority(newAuthority); + } + _setAuthority(newAuthority); + } + + /// @inheritdoc IAccessManaged + function isConsumingScheduledOp() public view returns (bytes4) { + return _consumingSchedule ? this.isConsumingScheduledOp.selector : bytes4(0); + } + + /** + * @dev Transfers control to a new authority. Internal function with no access restriction. Allows bypassing the + * permissions set by the current authority. + */ + function _setAuthority(address newAuthority) internal virtual { + _authority = newAuthority; + emit AuthorityUpdated(newAuthority); + } + + /** + * @dev Reverts if the caller is not allowed to call the function identified by a selector. Panics if the calldata + * is less than 4 bytes long. + */ + function _checkCanCall(address caller, bytes calldata data) internal virtual { + (bool immediate, uint32 delay) = AuthorityUtils.canCallWithDelay( + authority(), + caller, + address(this), + bytes4(data[0:4]) + ); + if (!immediate) { + if (delay > 0) { + _consumingSchedule = true; + IAccessManager(authority()).consumeScheduledOp(caller, data); + _consumingSchedule = false; + } else { + revert AccessManagedUnauthorized(caller); + } + } + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/access/manager/AccessManager.sol b/dependencies/@openzeppelin-contracts-5.4.0/access/manager/AccessManager.sol new file mode 100644 index 00000000..05108055 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/access/manager/AccessManager.sol @@ -0,0 +1,740 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.1.0) (access/manager/AccessManager.sol) + +pragma solidity ^0.8.20; + +import {IAccessManager} from "./IAccessManager.sol"; +import {IAccessManaged} from "./IAccessManaged.sol"; +import {Address} from "../../utils/Address.sol"; +import {Context} from "../../utils/Context.sol"; +import {Multicall} from "../../utils/Multicall.sol"; +import {Math} from "../../utils/math/Math.sol"; +import {Time} from "../../utils/types/Time.sol"; + +/** + * @dev AccessManager is a central contract to store the permissions of a system. + * + * A smart contract under the control of an AccessManager instance is known as a target, and will inherit from the + * {AccessManaged} contract, be connected to this contract as its manager and implement the {AccessManaged-restricted} + * modifier on a set of functions selected to be permissioned. Note that any function without this setup won't be + * effectively restricted. + * + * The restriction rules for such functions are defined in terms of "roles" identified by an `uint64` and scoped + * by target (`address`) and function selectors (`bytes4`). These roles are stored in this contract and can be + * configured by admins (`ADMIN_ROLE` members) after a delay (see {getTargetAdminDelay}). + * + * For each target contract, admins can configure the following without any delay: + * + * * The target's {AccessManaged-authority} via {updateAuthority}. + * * Close or open a target via {setTargetClosed} keeping the permissions intact. + * * The roles that are allowed (or disallowed) to call a given function (identified by its selector) through {setTargetFunctionRole}. + * + * By default every address is member of the `PUBLIC_ROLE` and every target function is restricted to the `ADMIN_ROLE` until configured otherwise. + * Additionally, each role has the following configuration options restricted to this manager's admins: + * + * * A role's admin role via {setRoleAdmin} who can grant or revoke roles. + * * A role's guardian role via {setRoleGuardian} who's allowed to cancel operations. + * * A delay in which a role takes effect after being granted through {setGrantDelay}. + * * A delay of any target's admin action via {setTargetAdminDelay}. + * * A role label for discoverability purposes with {labelRole}. + * + * Any account can be added and removed into any number of these roles by using the {grantRole} and {revokeRole} functions + * restricted to each role's admin (see {getRoleAdmin}). + * + * Since all the permissions of the managed system can be modified by the admins of this instance, it is expected that + * they will be highly secured (e.g., a multisig or a well-configured DAO). + * + * NOTE: This contract implements a form of the {IAuthority} interface, but {canCall} has additional return data so it + * doesn't inherit `IAuthority`. It is however compatible with the `IAuthority` interface since the first 32 bytes of + * the return data are a boolean as expected by that interface. + * + * NOTE: Systems that implement other access control mechanisms (for example using {Ownable}) can be paired with an + * {AccessManager} by transferring permissions (ownership in the case of {Ownable}) directly to the {AccessManager}. + * Users will be able to interact with these contracts through the {execute} function, following the access rules + * registered in the {AccessManager}. Keep in mind that in that context, the msg.sender seen by restricted functions + * will be {AccessManager} itself. + * + * WARNING: When granting permissions over an {Ownable} or {AccessControl} contract to an {AccessManager}, be very + * mindful of the danger associated with functions such as {Ownable-renounceOwnership} or + * {AccessControl-renounceRole}. + */ +contract AccessManager is Context, Multicall, IAccessManager { + using Time for *; + + // Structure that stores the details for a target contract. + struct TargetConfig { + mapping(bytes4 selector => uint64 roleId) allowedRoles; + Time.Delay adminDelay; + bool closed; + } + + // Structure that stores the details for a role/account pair. This structures fit into a single slot. + struct Access { + // Timepoint at which the user gets the permission. + // If this is either 0 or in the future, then the role permission is not available. + uint48 since; + // Delay for execution. Only applies to restricted() / execute() calls. + Time.Delay delay; + } + + // Structure that stores the details of a role. + struct Role { + // Members of the role. + mapping(address user => Access access) members; + // Admin who can grant or revoke permissions. + uint64 admin; + // Guardian who can cancel operations targeting functions that need this role. + uint64 guardian; + // Delay in which the role takes effect after being granted. + Time.Delay grantDelay; + } + + // Structure that stores the details for a scheduled operation. This structure fits into a single slot. + struct Schedule { + // Moment at which the operation can be executed. + uint48 timepoint; + // Operation nonce to allow third-party contracts to identify the operation. + uint32 nonce; + } + + /** + * @dev The identifier of the admin role. Required to perform most configuration operations including + * other roles' management and target restrictions. + */ + uint64 public constant ADMIN_ROLE = type(uint64).min; // 0 + + /** + * @dev The identifier of the public role. Automatically granted to all addresses with no delay. + */ + uint64 public constant PUBLIC_ROLE = type(uint64).max; // 2**64-1 + + mapping(address target => TargetConfig mode) private _targets; + mapping(uint64 roleId => Role) private _roles; + mapping(bytes32 operationId => Schedule) private _schedules; + + // Used to identify operations that are currently being executed via {execute}. + // This should be transient storage when supported by the EVM. + bytes32 private _executionId; + + /** + * @dev Check that the caller is authorized to perform the operation. + * See {AccessManager} description for a detailed breakdown of the authorization logic. + */ + modifier onlyAuthorized() { + _checkAuthorized(); + _; + } + + constructor(address initialAdmin) { + if (initialAdmin == address(0)) { + revert AccessManagerInvalidInitialAdmin(address(0)); + } + + // admin is active immediately and without any execution delay. + _grantRole(ADMIN_ROLE, initialAdmin, 0, 0); + } + + // =================================================== GETTERS ==================================================== + /// @inheritdoc IAccessManager + function canCall( + address caller, + address target, + bytes4 selector + ) public view virtual returns (bool immediate, uint32 delay) { + if (isTargetClosed(target)) { + return (false, 0); + } else if (caller == address(this)) { + // Caller is AccessManager, this means the call was sent through {execute} and it already checked + // permissions. We verify that the call "identifier", which is set during {execute}, is correct. + return (_isExecuting(target, selector), 0); + } else { + uint64 roleId = getTargetFunctionRole(target, selector); + (bool isMember, uint32 currentDelay) = hasRole(roleId, caller); + return isMember ? (currentDelay == 0, currentDelay) : (false, 0); + } + } + + /// @inheritdoc IAccessManager + function expiration() public view virtual returns (uint32) { + return 1 weeks; + } + + /// @inheritdoc IAccessManager + function minSetback() public view virtual returns (uint32) { + return 5 days; + } + + /// @inheritdoc IAccessManager + function isTargetClosed(address target) public view virtual returns (bool) { + return _targets[target].closed; + } + + /// @inheritdoc IAccessManager + function getTargetFunctionRole(address target, bytes4 selector) public view virtual returns (uint64) { + return _targets[target].allowedRoles[selector]; + } + + /// @inheritdoc IAccessManager + function getTargetAdminDelay(address target) public view virtual returns (uint32) { + return _targets[target].adminDelay.get(); + } + + /// @inheritdoc IAccessManager + function getRoleAdmin(uint64 roleId) public view virtual returns (uint64) { + return _roles[roleId].admin; + } + + /// @inheritdoc IAccessManager + function getRoleGuardian(uint64 roleId) public view virtual returns (uint64) { + return _roles[roleId].guardian; + } + + /// @inheritdoc IAccessManager + function getRoleGrantDelay(uint64 roleId) public view virtual returns (uint32) { + return _roles[roleId].grantDelay.get(); + } + + /// @inheritdoc IAccessManager + function getAccess( + uint64 roleId, + address account + ) public view virtual returns (uint48 since, uint32 currentDelay, uint32 pendingDelay, uint48 effect) { + Access storage access = _roles[roleId].members[account]; + + since = access.since; + (currentDelay, pendingDelay, effect) = access.delay.getFull(); + + return (since, currentDelay, pendingDelay, effect); + } + + /// @inheritdoc IAccessManager + function hasRole( + uint64 roleId, + address account + ) public view virtual returns (bool isMember, uint32 executionDelay) { + if (roleId == PUBLIC_ROLE) { + return (true, 0); + } else { + (uint48 hasRoleSince, uint32 currentDelay, , ) = getAccess(roleId, account); + return (hasRoleSince != 0 && hasRoleSince <= Time.timestamp(), currentDelay); + } + } + + // =============================================== ROLE MANAGEMENT =============================================== + /// @inheritdoc IAccessManager + function labelRole(uint64 roleId, string calldata label) public virtual onlyAuthorized { + if (roleId == ADMIN_ROLE || roleId == PUBLIC_ROLE) { + revert AccessManagerLockedRole(roleId); + } + emit RoleLabel(roleId, label); + } + + /// @inheritdoc IAccessManager + function grantRole(uint64 roleId, address account, uint32 executionDelay) public virtual onlyAuthorized { + _grantRole(roleId, account, getRoleGrantDelay(roleId), executionDelay); + } + + /// @inheritdoc IAccessManager + function revokeRole(uint64 roleId, address account) public virtual onlyAuthorized { + _revokeRole(roleId, account); + } + + /// @inheritdoc IAccessManager + function renounceRole(uint64 roleId, address callerConfirmation) public virtual { + if (callerConfirmation != _msgSender()) { + revert AccessManagerBadConfirmation(); + } + _revokeRole(roleId, callerConfirmation); + } + + /// @inheritdoc IAccessManager + function setRoleAdmin(uint64 roleId, uint64 admin) public virtual onlyAuthorized { + _setRoleAdmin(roleId, admin); + } + + /// @inheritdoc IAccessManager + function setRoleGuardian(uint64 roleId, uint64 guardian) public virtual onlyAuthorized { + _setRoleGuardian(roleId, guardian); + } + + /// @inheritdoc IAccessManager + function setGrantDelay(uint64 roleId, uint32 newDelay) public virtual onlyAuthorized { + _setGrantDelay(roleId, newDelay); + } + + /** + * @dev Internal version of {grantRole} without access control. Returns true if the role was newly granted. + * + * Emits a {RoleGranted} event. + */ + function _grantRole( + uint64 roleId, + address account, + uint32 grantDelay, + uint32 executionDelay + ) internal virtual returns (bool) { + if (roleId == PUBLIC_ROLE) { + revert AccessManagerLockedRole(roleId); + } + + bool newMember = _roles[roleId].members[account].since == 0; + uint48 since; + + if (newMember) { + since = Time.timestamp() + grantDelay; + _roles[roleId].members[account] = Access({since: since, delay: executionDelay.toDelay()}); + } else { + // No setback here. Value can be reset by doing revoke + grant, effectively allowing the admin to perform + // any change to the execution delay within the duration of the role admin delay. + (_roles[roleId].members[account].delay, since) = _roles[roleId].members[account].delay.withUpdate( + executionDelay, + 0 + ); + } + + emit RoleGranted(roleId, account, executionDelay, since, newMember); + return newMember; + } + + /** + * @dev Internal version of {revokeRole} without access control. This logic is also used by {renounceRole}. + * Returns true if the role was previously granted. + * + * Emits a {RoleRevoked} event if the account had the role. + */ + function _revokeRole(uint64 roleId, address account) internal virtual returns (bool) { + if (roleId == PUBLIC_ROLE) { + revert AccessManagerLockedRole(roleId); + } + + if (_roles[roleId].members[account].since == 0) { + return false; + } + + delete _roles[roleId].members[account]; + + emit RoleRevoked(roleId, account); + return true; + } + + /** + * @dev Internal version of {setRoleAdmin} without access control. + * + * Emits a {RoleAdminChanged} event. + * + * NOTE: Setting the admin role as the `PUBLIC_ROLE` is allowed, but it will effectively allow + * anyone to set grant or revoke such role. + */ + function _setRoleAdmin(uint64 roleId, uint64 admin) internal virtual { + if (roleId == ADMIN_ROLE || roleId == PUBLIC_ROLE) { + revert AccessManagerLockedRole(roleId); + } + + _roles[roleId].admin = admin; + + emit RoleAdminChanged(roleId, admin); + } + + /** + * @dev Internal version of {setRoleGuardian} without access control. + * + * Emits a {RoleGuardianChanged} event. + * + * NOTE: Setting the guardian role as the `PUBLIC_ROLE` is allowed, but it will effectively allow + * anyone to cancel any scheduled operation for such role. + */ + function _setRoleGuardian(uint64 roleId, uint64 guardian) internal virtual { + if (roleId == ADMIN_ROLE || roleId == PUBLIC_ROLE) { + revert AccessManagerLockedRole(roleId); + } + + _roles[roleId].guardian = guardian; + + emit RoleGuardianChanged(roleId, guardian); + } + + /** + * @dev Internal version of {setGrantDelay} without access control. + * + * Emits a {RoleGrantDelayChanged} event. + */ + function _setGrantDelay(uint64 roleId, uint32 newDelay) internal virtual { + if (roleId == PUBLIC_ROLE) { + revert AccessManagerLockedRole(roleId); + } + + uint48 effect; + (_roles[roleId].grantDelay, effect) = _roles[roleId].grantDelay.withUpdate(newDelay, minSetback()); + + emit RoleGrantDelayChanged(roleId, newDelay, effect); + } + + // ============================================= FUNCTION MANAGEMENT ============================================== + /// @inheritdoc IAccessManager + function setTargetFunctionRole( + address target, + bytes4[] calldata selectors, + uint64 roleId + ) public virtual onlyAuthorized { + for (uint256 i = 0; i < selectors.length; ++i) { + _setTargetFunctionRole(target, selectors[i], roleId); + } + } + + /** + * @dev Internal version of {setTargetFunctionRole} without access control. + * + * Emits a {TargetFunctionRoleUpdated} event. + */ + function _setTargetFunctionRole(address target, bytes4 selector, uint64 roleId) internal virtual { + _targets[target].allowedRoles[selector] = roleId; + emit TargetFunctionRoleUpdated(target, selector, roleId); + } + + /// @inheritdoc IAccessManager + function setTargetAdminDelay(address target, uint32 newDelay) public virtual onlyAuthorized { + _setTargetAdminDelay(target, newDelay); + } + + /** + * @dev Internal version of {setTargetAdminDelay} without access control. + * + * Emits a {TargetAdminDelayUpdated} event. + */ + function _setTargetAdminDelay(address target, uint32 newDelay) internal virtual { + uint48 effect; + (_targets[target].adminDelay, effect) = _targets[target].adminDelay.withUpdate(newDelay, minSetback()); + + emit TargetAdminDelayUpdated(target, newDelay, effect); + } + + // =============================================== MODE MANAGEMENT ================================================ + /// @inheritdoc IAccessManager + function setTargetClosed(address target, bool closed) public virtual onlyAuthorized { + _setTargetClosed(target, closed); + } + + /** + * @dev Set the closed flag for a contract. This is an internal setter with no access restrictions. + * + * Emits a {TargetClosed} event. + */ + function _setTargetClosed(address target, bool closed) internal virtual { + _targets[target].closed = closed; + emit TargetClosed(target, closed); + } + + // ============================================== DELAYED OPERATIONS ============================================== + /// @inheritdoc IAccessManager + function getSchedule(bytes32 id) public view virtual returns (uint48) { + uint48 timepoint = _schedules[id].timepoint; + return _isExpired(timepoint) ? 0 : timepoint; + } + + /// @inheritdoc IAccessManager + function getNonce(bytes32 id) public view virtual returns (uint32) { + return _schedules[id].nonce; + } + + /// @inheritdoc IAccessManager + function schedule( + address target, + bytes calldata data, + uint48 when + ) public virtual returns (bytes32 operationId, uint32 nonce) { + address caller = _msgSender(); + + // Fetch restrictions that apply to the caller on the targeted function + (, uint32 setback) = _canCallExtended(caller, target, data); + + uint48 minWhen = Time.timestamp() + setback; + + // If call with delay is not authorized, or if requested timing is too soon, revert + if (setback == 0 || (when > 0 && when < minWhen)) { + revert AccessManagerUnauthorizedCall(caller, target, _checkSelector(data)); + } + + // Reuse variable due to stack too deep + when = uint48(Math.max(when, minWhen)); // cast is safe: both inputs are uint48 + + // If caller is authorised, schedule operation + operationId = hashOperation(caller, target, data); + + _checkNotScheduled(operationId); + + unchecked { + // It's not feasible to overflow the nonce in less than 1000 years + nonce = _schedules[operationId].nonce + 1; + } + _schedules[operationId].timepoint = when; + _schedules[operationId].nonce = nonce; + emit OperationScheduled(operationId, nonce, when, caller, target, data); + + // Using named return values because otherwise we get stack too deep + } + + /** + * @dev Reverts if the operation is currently scheduled and has not expired. + * + * NOTE: This function was introduced due to stack too deep errors in schedule. + */ + function _checkNotScheduled(bytes32 operationId) private view { + uint48 prevTimepoint = _schedules[operationId].timepoint; + if (prevTimepoint != 0 && !_isExpired(prevTimepoint)) { + revert AccessManagerAlreadyScheduled(operationId); + } + } + + /// @inheritdoc IAccessManager + // Reentrancy is not an issue because permissions are checked on msg.sender. Additionally, + // _consumeScheduledOp guarantees a scheduled operation is only executed once. + // slither-disable-next-line reentrancy-no-eth + function execute(address target, bytes calldata data) public payable virtual returns (uint32) { + address caller = _msgSender(); + + // Fetch restrictions that apply to the caller on the targeted function + (bool immediate, uint32 setback) = _canCallExtended(caller, target, data); + + // If call is not authorized, revert + if (!immediate && setback == 0) { + revert AccessManagerUnauthorizedCall(caller, target, _checkSelector(data)); + } + + bytes32 operationId = hashOperation(caller, target, data); + uint32 nonce; + + // If caller is authorised, check operation was scheduled early enough + // Consume an available schedule even if there is no currently enforced delay + if (setback != 0 || getSchedule(operationId) != 0) { + nonce = _consumeScheduledOp(operationId); + } + + // Mark the target and selector as authorised + bytes32 executionIdBefore = _executionId; + _executionId = _hashExecutionId(target, _checkSelector(data)); + + // Perform call + Address.functionCallWithValue(target, data, msg.value); + + // Reset execute identifier + _executionId = executionIdBefore; + + return nonce; + } + + /// @inheritdoc IAccessManager + function cancel(address caller, address target, bytes calldata data) public virtual returns (uint32) { + address msgsender = _msgSender(); + bytes4 selector = _checkSelector(data); + + bytes32 operationId = hashOperation(caller, target, data); + if (_schedules[operationId].timepoint == 0) { + revert AccessManagerNotScheduled(operationId); + } else if (caller != msgsender) { + // calls can only be canceled by the account that scheduled them, a global admin, or by a guardian of the required role. + (bool isAdmin, ) = hasRole(ADMIN_ROLE, msgsender); + (bool isGuardian, ) = hasRole(getRoleGuardian(getTargetFunctionRole(target, selector)), msgsender); + if (!isAdmin && !isGuardian) { + revert AccessManagerUnauthorizedCancel(msgsender, caller, target, selector); + } + } + + delete _schedules[operationId].timepoint; // reset the timepoint, keep the nonce + uint32 nonce = _schedules[operationId].nonce; + emit OperationCanceled(operationId, nonce); + + return nonce; + } + + /// @inheritdoc IAccessManager + function consumeScheduledOp(address caller, bytes calldata data) public virtual { + address target = _msgSender(); + if (IAccessManaged(target).isConsumingScheduledOp() != IAccessManaged.isConsumingScheduledOp.selector) { + revert AccessManagerUnauthorizedConsume(target); + } + _consumeScheduledOp(hashOperation(caller, target, data)); + } + + /** + * @dev Internal variant of {consumeScheduledOp} that operates on bytes32 operationId. + * + * Returns the nonce of the scheduled operation that is consumed. + */ + function _consumeScheduledOp(bytes32 operationId) internal virtual returns (uint32) { + uint48 timepoint = _schedules[operationId].timepoint; + uint32 nonce = _schedules[operationId].nonce; + + if (timepoint == 0) { + revert AccessManagerNotScheduled(operationId); + } else if (timepoint > Time.timestamp()) { + revert AccessManagerNotReady(operationId); + } else if (_isExpired(timepoint)) { + revert AccessManagerExpired(operationId); + } + + delete _schedules[operationId].timepoint; // reset the timepoint, keep the nonce + emit OperationExecuted(operationId, nonce); + + return nonce; + } + + /// @inheritdoc IAccessManager + function hashOperation(address caller, address target, bytes calldata data) public view virtual returns (bytes32) { + return keccak256(abi.encode(caller, target, data)); + } + + // ==================================================== OTHERS ==================================================== + /// @inheritdoc IAccessManager + function updateAuthority(address target, address newAuthority) public virtual onlyAuthorized { + IAccessManaged(target).setAuthority(newAuthority); + } + + // ================================================= ADMIN LOGIC ================================================== + /** + * @dev Check if the current call is authorized according to admin and roles logic. + * + * WARNING: Carefully review the considerations of {AccessManaged-restricted} since they apply to this modifier. + */ + function _checkAuthorized() private { + address caller = _msgSender(); + (bool immediate, uint32 delay) = _canCallSelf(caller, _msgData()); + if (!immediate) { + if (delay == 0) { + (, uint64 requiredRole, ) = _getAdminRestrictions(_msgData()); + revert AccessManagerUnauthorizedAccount(caller, requiredRole); + } else { + _consumeScheduledOp(hashOperation(caller, address(this), _msgData())); + } + } + } + + /** + * @dev Get the admin restrictions of a given function call based on the function and arguments involved. + * + * Returns: + * - bool restricted: does this data match a restricted operation + * - uint64: which role is this operation restricted to + * - uint32: minimum delay to enforce for that operation (max between operation's delay and admin's execution delay) + */ + function _getAdminRestrictions( + bytes calldata data + ) private view returns (bool adminRestricted, uint64 roleAdminId, uint32 executionDelay) { + if (data.length < 4) { + return (false, 0, 0); + } + + bytes4 selector = _checkSelector(data); + + // Restricted to ADMIN with no delay beside any execution delay the caller may have + if ( + selector == this.labelRole.selector || + selector == this.setRoleAdmin.selector || + selector == this.setRoleGuardian.selector || + selector == this.setGrantDelay.selector || + selector == this.setTargetAdminDelay.selector + ) { + return (true, ADMIN_ROLE, 0); + } + + // Restricted to ADMIN with the admin delay corresponding to the target + if ( + selector == this.updateAuthority.selector || + selector == this.setTargetClosed.selector || + selector == this.setTargetFunctionRole.selector + ) { + // First argument is a target. + address target = abi.decode(data[0x04:0x24], (address)); + uint32 delay = getTargetAdminDelay(target); + return (true, ADMIN_ROLE, delay); + } + + // Restricted to that role's admin with no delay beside any execution delay the caller may have. + if (selector == this.grantRole.selector || selector == this.revokeRole.selector) { + // First argument is a roleId. + uint64 roleId = abi.decode(data[0x04:0x24], (uint64)); + return (true, getRoleAdmin(roleId), 0); + } + + return (false, getTargetFunctionRole(address(this), selector), 0); + } + + // =================================================== HELPERS ==================================================== + /** + * @dev An extended version of {canCall} for internal usage that checks {_canCallSelf} + * when the target is this contract. + * + * Returns: + * - bool immediate: whether the operation can be executed immediately (with no delay) + * - uint32 delay: the execution delay + */ + function _canCallExtended( + address caller, + address target, + bytes calldata data + ) private view returns (bool immediate, uint32 delay) { + if (target == address(this)) { + return _canCallSelf(caller, data); + } else { + return data.length < 4 ? (false, 0) : canCall(caller, target, _checkSelector(data)); + } + } + + /** + * @dev A version of {canCall} that checks for restrictions in this contract. + */ + function _canCallSelf(address caller, bytes calldata data) private view returns (bool immediate, uint32 delay) { + if (data.length < 4) { + return (false, 0); + } + + if (caller == address(this)) { + // Caller is AccessManager, this means the call was sent through {execute} and it already checked + // permissions. We verify that the call "identifier", which is set during {execute}, is correct. + return (_isExecuting(address(this), _checkSelector(data)), 0); + } + + (bool adminRestricted, uint64 roleId, uint32 operationDelay) = _getAdminRestrictions(data); + + // isTargetClosed apply to non-admin-restricted function + if (!adminRestricted && isTargetClosed(address(this))) { + return (false, 0); + } + + (bool inRole, uint32 executionDelay) = hasRole(roleId, caller); + if (!inRole) { + return (false, 0); + } + + // downcast is safe because both options are uint32 + delay = uint32(Math.max(operationDelay, executionDelay)); + return (delay == 0, delay); + } + + /** + * @dev Returns true if a call with `target` and `selector` is being executed via {executed}. + */ + function _isExecuting(address target, bytes4 selector) private view returns (bool) { + return _executionId == _hashExecutionId(target, selector); + } + + /** + * @dev Returns true if a schedule timepoint is past its expiration deadline. + */ + function _isExpired(uint48 timepoint) private view returns (bool) { + return timepoint + expiration() <= Time.timestamp(); + } + + /** + * @dev Extracts the selector from calldata. Panics if data is not at least 4 bytes + */ + function _checkSelector(bytes calldata data) private pure returns (bytes4) { + return bytes4(data[0:4]); + } + + /** + * @dev Hashing function for execute protection + */ + function _hashExecutionId(address target, bytes4 selector) private pure returns (bytes32) { + return keccak256(abi.encode(target, selector)); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/access/manager/AuthorityUtils.sol b/dependencies/@openzeppelin-contracts-5.4.0/access/manager/AuthorityUtils.sol new file mode 100644 index 00000000..8b047096 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/access/manager/AuthorityUtils.sol @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.3.0) (access/manager/AuthorityUtils.sol) + +pragma solidity ^0.8.20; + +import {IAuthority} from "./IAuthority.sol"; + +library AuthorityUtils { + /** + * @dev Since `AccessManager` implements an extended IAuthority interface, invoking `canCall` with backwards compatibility + * for the preexisting `IAuthority` interface requires special care to avoid reverting on insufficient return data. + * This helper function takes care of invoking `canCall` in a backwards compatible way without reverting. + */ + function canCallWithDelay( + address authority, + address caller, + address target, + bytes4 selector + ) internal view returns (bool immediate, uint32 delay) { + bytes memory data = abi.encodeCall(IAuthority.canCall, (caller, target, selector)); + + assembly ("memory-safe") { + mstore(0x00, 0x00) + mstore(0x20, 0x00) + + if staticcall(gas(), authority, add(data, 0x20), mload(data), 0x00, 0x40) { + immediate := mload(0x00) + delay := mload(0x20) + + // If delay does not fit in a uint32, return 0 (no delay) + // equivalent to: if gt(delay, 0xFFFFFFFF) { delay := 0 } + delay := mul(delay, iszero(shr(32, delay))) + } + } + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/access/manager/IAccessManaged.sol b/dependencies/@openzeppelin-contracts-5.4.0/access/manager/IAccessManaged.sol new file mode 100644 index 00000000..c93c7119 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/access/manager/IAccessManaged.sol @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (access/manager/IAccessManaged.sol) + +pragma solidity >=0.8.4; + +interface IAccessManaged { + /** + * @dev Authority that manages this contract was updated. + */ + event AuthorityUpdated(address authority); + + error AccessManagedUnauthorized(address caller); + error AccessManagedRequiredDelay(address caller, uint32 delay); + error AccessManagedInvalidAuthority(address authority); + + /** + * @dev Returns the current authority. + */ + function authority() external view returns (address); + + /** + * @dev Transfers control to a new authority. The caller must be the current authority. + */ + function setAuthority(address) external; + + /** + * @dev Returns true only in the context of a delayed restricted call, at the moment that the scheduled operation is + * being consumed. Prevents denial of service for delayed restricted calls in the case that the contract performs + * attacker controlled calls. + */ + function isConsumingScheduledOp() external view returns (bytes4); +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/access/manager/IAccessManager.sol b/dependencies/@openzeppelin-contracts-5.4.0/access/manager/IAccessManager.sol new file mode 100644 index 00000000..925be907 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/access/manager/IAccessManager.sol @@ -0,0 +1,399 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (access/manager/IAccessManager.sol) + +pragma solidity >=0.8.4; + +interface IAccessManager { + /** + * @dev A delayed operation was scheduled. + */ + event OperationScheduled( + bytes32 indexed operationId, + uint32 indexed nonce, + uint48 schedule, + address caller, + address target, + bytes data + ); + + /** + * @dev A scheduled operation was executed. + */ + event OperationExecuted(bytes32 indexed operationId, uint32 indexed nonce); + + /** + * @dev A scheduled operation was canceled. + */ + event OperationCanceled(bytes32 indexed operationId, uint32 indexed nonce); + + /** + * @dev Informational labelling for a roleId. + */ + event RoleLabel(uint64 indexed roleId, string label); + + /** + * @dev Emitted when `account` is granted `roleId`. + * + * NOTE: The meaning of the `since` argument depends on the `newMember` argument. + * If the role is granted to a new member, the `since` argument indicates when the account becomes a member of the role, + * otherwise it indicates the execution delay for this account and roleId is updated. + */ + event RoleGranted(uint64 indexed roleId, address indexed account, uint32 delay, uint48 since, bool newMember); + + /** + * @dev Emitted when `account` membership or `roleId` is revoked. Unlike granting, revoking is instantaneous. + */ + event RoleRevoked(uint64 indexed roleId, address indexed account); + + /** + * @dev Role acting as admin over a given `roleId` is updated. + */ + event RoleAdminChanged(uint64 indexed roleId, uint64 indexed admin); + + /** + * @dev Role acting as guardian over a given `roleId` is updated. + */ + event RoleGuardianChanged(uint64 indexed roleId, uint64 indexed guardian); + + /** + * @dev Grant delay for a given `roleId` will be updated to `delay` when `since` is reached. + */ + event RoleGrantDelayChanged(uint64 indexed roleId, uint32 delay, uint48 since); + + /** + * @dev Target mode is updated (true = closed, false = open). + */ + event TargetClosed(address indexed target, bool closed); + + /** + * @dev Role required to invoke `selector` on `target` is updated to `roleId`. + */ + event TargetFunctionRoleUpdated(address indexed target, bytes4 selector, uint64 indexed roleId); + + /** + * @dev Admin delay for a given `target` will be updated to `delay` when `since` is reached. + */ + event TargetAdminDelayUpdated(address indexed target, uint32 delay, uint48 since); + + error AccessManagerAlreadyScheduled(bytes32 operationId); + error AccessManagerNotScheduled(bytes32 operationId); + error AccessManagerNotReady(bytes32 operationId); + error AccessManagerExpired(bytes32 operationId); + error AccessManagerLockedRole(uint64 roleId); + error AccessManagerBadConfirmation(); + error AccessManagerUnauthorizedAccount(address msgsender, uint64 roleId); + error AccessManagerUnauthorizedCall(address caller, address target, bytes4 selector); + error AccessManagerUnauthorizedConsume(address target); + error AccessManagerUnauthorizedCancel(address msgsender, address caller, address target, bytes4 selector); + error AccessManagerInvalidInitialAdmin(address initialAdmin); + + /** + * @dev Check if an address (`caller`) is authorised to call a given function on a given contract directly (with + * no restriction). Additionally, it returns the delay needed to perform the call indirectly through the {schedule} + * & {execute} workflow. + * + * This function is usually called by the targeted contract to control immediate execution of restricted functions. + * Therefore we only return true if the call can be performed without any delay. If the call is subject to a + * previously set delay (not zero), then the function should return false and the caller should schedule the operation + * for future execution. + * + * If `allowed` is true, the delay can be disregarded and the operation can be immediately executed, otherwise + * the operation can be executed if and only if delay is greater than 0. + * + * NOTE: The IAuthority interface does not include the `uint32` delay. This is an extension of that interface that + * is backward compatible. Some contracts may thus ignore the second return argument. In that case they will fail + * to identify the indirect workflow, and will consider calls that require a delay to be forbidden. + * + * NOTE: This function does not report the permissions of the admin functions in the manager itself. These are defined by the + * {AccessManager} documentation. + */ + function canCall( + address caller, + address target, + bytes4 selector + ) external view returns (bool allowed, uint32 delay); + + /** + * @dev Expiration delay for scheduled proposals. Defaults to 1 week. + * + * IMPORTANT: Avoid overriding the expiration with 0. Otherwise every contract proposal will be expired immediately, + * disabling any scheduling usage. + */ + function expiration() external view returns (uint32); + + /** + * @dev Minimum setback for all delay updates, with the exception of execution delays. It + * can be increased without setback (and reset via {revokeRole} in the case event of an + * accidental increase). Defaults to 5 days. + */ + function minSetback() external view returns (uint32); + + /** + * @dev Get whether the contract is closed disabling any access. Otherwise role permissions are applied. + * + * NOTE: When the manager itself is closed, admin functions are still accessible to avoid locking the contract. + */ + function isTargetClosed(address target) external view returns (bool); + + /** + * @dev Get the role required to call a function. + */ + function getTargetFunctionRole(address target, bytes4 selector) external view returns (uint64); + + /** + * @dev Get the admin delay for a target contract. Changes to contract configuration are subject to this delay. + */ + function getTargetAdminDelay(address target) external view returns (uint32); + + /** + * @dev Get the id of the role that acts as an admin for the given role. + * + * The admin permission is required to grant the role, revoke the role and update the execution delay to execute + * an operation that is restricted to this role. + */ + function getRoleAdmin(uint64 roleId) external view returns (uint64); + + /** + * @dev Get the role that acts as a guardian for a given role. + * + * The guardian permission allows canceling operations that have been scheduled under the role. + */ + function getRoleGuardian(uint64 roleId) external view returns (uint64); + + /** + * @dev Get the role current grant delay. + * + * Its value may change at any point without an event emitted following a call to {setGrantDelay}. + * Changes to this value, including effect timepoint are notified in advance by the {RoleGrantDelayChanged} event. + */ + function getRoleGrantDelay(uint64 roleId) external view returns (uint32); + + /** + * @dev Get the access details for a given account for a given role. These details include the timepoint at which + * membership becomes active, and the delay applied to all operation by this user that requires this permission + * level. + * + * Returns: + * [0] Timestamp at which the account membership becomes valid. 0 means role is not granted. + * [1] Current execution delay for the account. + * [2] Pending execution delay for the account. + * [3] Timestamp at which the pending execution delay will become active. 0 means no delay update is scheduled. + */ + function getAccess( + uint64 roleId, + address account + ) external view returns (uint48 since, uint32 currentDelay, uint32 pendingDelay, uint48 effect); + + /** + * @dev Check if a given account currently has the permission level corresponding to a given role. Note that this + * permission might be associated with an execution delay. {getAccess} can provide more details. + */ + function hasRole(uint64 roleId, address account) external view returns (bool isMember, uint32 executionDelay); + + /** + * @dev Give a label to a role, for improved role discoverability by UIs. + * + * Requirements: + * + * - the caller must be a global admin + * + * Emits a {RoleLabel} event. + */ + function labelRole(uint64 roleId, string calldata label) external; + + /** + * @dev Add `account` to `roleId`, or change its execution delay. + * + * This gives the account the authorization to call any function that is restricted to this role. An optional + * execution delay (in seconds) can be set. If that delay is non 0, the user is required to schedule any operation + * that is restricted to members of this role. The user will only be able to execute the operation after the delay has + * passed, before it has expired. During this period, admin and guardians can cancel the operation (see {cancel}). + * + * If the account has already been granted this role, the execution delay will be updated. This update is not + * immediate and follows the delay rules. For example, if a user currently has a delay of 3 hours, and this is + * called to reduce that delay to 1 hour, the new delay will take some time to take effect, enforcing that any + * operation executed in the 3 hours that follows this update was indeed scheduled before this update. + * + * Requirements: + * + * - the caller must be an admin for the role (see {getRoleAdmin}) + * - granted role must not be the `PUBLIC_ROLE` + * + * Emits a {RoleGranted} event. + */ + function grantRole(uint64 roleId, address account, uint32 executionDelay) external; + + /** + * @dev Remove an account from a role, with immediate effect. If the account does not have the role, this call has + * no effect. + * + * Requirements: + * + * - the caller must be an admin for the role (see {getRoleAdmin}) + * - revoked role must not be the `PUBLIC_ROLE` + * + * Emits a {RoleRevoked} event if the account had the role. + */ + function revokeRole(uint64 roleId, address account) external; + + /** + * @dev Renounce role permissions for the calling account with immediate effect. If the sender is not in + * the role this call has no effect. + * + * Requirements: + * + * - the caller must be `callerConfirmation`. + * + * Emits a {RoleRevoked} event if the account had the role. + */ + function renounceRole(uint64 roleId, address callerConfirmation) external; + + /** + * @dev Change admin role for a given role. + * + * Requirements: + * + * - the caller must be a global admin + * + * Emits a {RoleAdminChanged} event + */ + function setRoleAdmin(uint64 roleId, uint64 admin) external; + + /** + * @dev Change guardian role for a given role. + * + * Requirements: + * + * - the caller must be a global admin + * + * Emits a {RoleGuardianChanged} event + */ + function setRoleGuardian(uint64 roleId, uint64 guardian) external; + + /** + * @dev Update the delay for granting a `roleId`. + * + * Requirements: + * + * - the caller must be a global admin + * + * Emits a {RoleGrantDelayChanged} event. + */ + function setGrantDelay(uint64 roleId, uint32 newDelay) external; + + /** + * @dev Set the role required to call functions identified by the `selectors` in the `target` contract. + * + * Requirements: + * + * - the caller must be a global admin + * + * Emits a {TargetFunctionRoleUpdated} event per selector. + */ + function setTargetFunctionRole(address target, bytes4[] calldata selectors, uint64 roleId) external; + + /** + * @dev Set the delay for changing the configuration of a given target contract. + * + * Requirements: + * + * - the caller must be a global admin + * + * Emits a {TargetAdminDelayUpdated} event. + */ + function setTargetAdminDelay(address target, uint32 newDelay) external; + + /** + * @dev Set the closed flag for a contract. + * + * Closing the manager itself won't disable access to admin methods to avoid locking the contract. + * + * Requirements: + * + * - the caller must be a global admin + * + * Emits a {TargetClosed} event. + */ + function setTargetClosed(address target, bool closed) external; + + /** + * @dev Return the timepoint at which a scheduled operation will be ready for execution. This returns 0 if the + * operation is not yet scheduled, has expired, was executed, or was canceled. + */ + function getSchedule(bytes32 id) external view returns (uint48); + + /** + * @dev Return the nonce for the latest scheduled operation with a given id. Returns 0 if the operation has never + * been scheduled. + */ + function getNonce(bytes32 id) external view returns (uint32); + + /** + * @dev Schedule a delayed operation for future execution, and return the operation identifier. It is possible to + * choose the timestamp at which the operation becomes executable as long as it satisfies the execution delays + * required for the caller. The special value zero will automatically set the earliest possible time. + * + * Returns the `operationId` that was scheduled. Since this value is a hash of the parameters, it can reoccur when + * the same parameters are used; if this is relevant, the returned `nonce` can be used to uniquely identify this + * scheduled operation from other occurrences of the same `operationId` in invocations of {execute} and {cancel}. + * + * Emits a {OperationScheduled} event. + * + * NOTE: It is not possible to concurrently schedule more than one operation with the same `target` and `data`. If + * this is necessary, a random byte can be appended to `data` to act as a salt that will be ignored by the target + * contract if it is using standard Solidity ABI encoding. + */ + function schedule( + address target, + bytes calldata data, + uint48 when + ) external returns (bytes32 operationId, uint32 nonce); + + /** + * @dev Execute a function that is delay restricted, provided it was properly scheduled beforehand, or the + * execution delay is 0. + * + * Returns the nonce that identifies the previously scheduled operation that is executed, or 0 if the + * operation wasn't previously scheduled (if the caller doesn't have an execution delay). + * + * Emits an {OperationExecuted} event only if the call was scheduled and delayed. + */ + function execute(address target, bytes calldata data) external payable returns (uint32); + + /** + * @dev Cancel a scheduled (delayed) operation. Returns the nonce that identifies the previously scheduled + * operation that is cancelled. + * + * Requirements: + * + * - the caller must be the proposer, a guardian of the targeted function, or a global admin + * + * Emits a {OperationCanceled} event. + */ + function cancel(address caller, address target, bytes calldata data) external returns (uint32); + + /** + * @dev Consume a scheduled operation targeting the caller. If such an operation exists, mark it as consumed + * (emit an {OperationExecuted} event and clean the state). Otherwise, throw an error. + * + * This is useful for contract that want to enforce that calls targeting them were scheduled on the manager, + * with all the verifications that it implies. + * + * Emit a {OperationExecuted} event. + */ + function consumeScheduledOp(address caller, bytes calldata data) external; + + /** + * @dev Hashing function for delayed operations. + */ + function hashOperation(address caller, address target, bytes calldata data) external view returns (bytes32); + + /** + * @dev Changes the authority of a target managed by this manager instance. + * + * Requirements: + * + * - the caller must be a global admin + */ + function updateAuthority(address target, address newAuthority) external; +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/access/manager/IAuthority.sol b/dependencies/@openzeppelin-contracts-5.4.0/access/manager/IAuthority.sol new file mode 100644 index 00000000..6ad902c7 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/access/manager/IAuthority.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (access/manager/IAuthority.sol) + +pragma solidity >=0.4.16; + +/** + * @dev Standard interface for permissioning originally defined in Dappsys. + */ +interface IAuthority { + /** + * @dev Returns true if the caller can invoke on a target the function identified by a function selector. + */ + function canCall(address caller, address target, bytes4 selector) external view returns (bool allowed); +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/account/Account.sol b/dependencies/@openzeppelin-contracts-5.4.0/account/Account.sol new file mode 100644 index 00000000..19c64d7a --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/account/Account.sol @@ -0,0 +1,145 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (account/Account.sol) + +pragma solidity ^0.8.20; + +import {PackedUserOperation, IAccount, IEntryPoint} from "../interfaces/draft-IERC4337.sol"; +import {ERC4337Utils} from "./utils/draft-ERC4337Utils.sol"; +import {AbstractSigner} from "../utils/cryptography/signers/AbstractSigner.sol"; + +/** + * @dev A simple ERC4337 account implementation. This base implementation only includes the minimal logic to process + * user operations. + * + * Developers must implement the {AbstractSigner-_rawSignatureValidation} function to define the account's validation logic. + * + * NOTE: This core account doesn't include any mechanism for performing arbitrary external calls. This is an essential + * feature that all Account should have. We leave it up to the developers to implement the mechanism of their choice. + * Common choices include ERC-6900, ERC-7579 and ERC-7821 (among others). + * + * IMPORTANT: Implementing a mechanism to validate signatures is a security-sensitive operation as it may allow an + * attacker to bypass the account's security measures. Check out {SignerECDSA}, {SignerP256}, or {SignerRSA} for + * digital signature validation implementations. + * + * @custom:stateless + */ +abstract contract Account is AbstractSigner, IAccount { + /** + * @dev Unauthorized call to the account. + */ + error AccountUnauthorized(address sender); + + /** + * @dev Revert if the caller is not the entry point or the account itself. + */ + modifier onlyEntryPointOrSelf() { + _checkEntryPointOrSelf(); + _; + } + + /** + * @dev Revert if the caller is not the entry point. + */ + modifier onlyEntryPoint() { + _checkEntryPoint(); + _; + } + + /** + * @dev Canonical entry point for the account that forwards and validates user operations. + */ + function entryPoint() public view virtual returns (IEntryPoint) { + return ERC4337Utils.ENTRYPOINT_V08; + } + + /** + * @dev Return the account nonce for the canonical sequence. + */ + function getNonce() public view virtual returns (uint256) { + return getNonce(0); + } + + /** + * @dev Return the account nonce for a given sequence (key). + */ + function getNonce(uint192 key) public view virtual returns (uint256) { + return entryPoint().getNonce(address(this), key); + } + + /** + * @inheritdoc IAccount + */ + function validateUserOp( + PackedUserOperation calldata userOp, + bytes32 userOpHash, + uint256 missingAccountFunds + ) public virtual onlyEntryPoint returns (uint256) { + uint256 validationData = _validateUserOp(userOp, userOpHash); + _payPrefund(missingAccountFunds); + return validationData; + } + + /** + * @dev Returns the validationData for a given user operation. By default, this checks the signature of the + * signable hash (produced by {_signableUserOpHash}) using the abstract signer ({AbstractSigner-_rawSignatureValidation}). + * + * NOTE: The userOpHash is assumed to be correct. Calling this function with a userOpHash that does not match the + * userOp will result in undefined behavior. + */ + function _validateUserOp( + PackedUserOperation calldata userOp, + bytes32 userOpHash + ) internal virtual returns (uint256) { + return + _rawSignatureValidation(_signableUserOpHash(userOp, userOpHash), userOp.signature) + ? ERC4337Utils.SIG_VALIDATION_SUCCESS + : ERC4337Utils.SIG_VALIDATION_FAILED; + } + + /** + * @dev Virtual function that returns the signable hash for a user operations. Since v0.8.0 of the entrypoint, + * `userOpHash` is an EIP-712 hash that can be signed directly. + */ + function _signableUserOpHash( + PackedUserOperation calldata /*userOp*/, + bytes32 userOpHash + ) internal view virtual returns (bytes32) { + return userOpHash; + } + + /** + * @dev Sends the missing funds for executing the user operation to the {entrypoint}. + * The `missingAccountFunds` must be defined by the entrypoint when calling {validateUserOp}. + */ + function _payPrefund(uint256 missingAccountFunds) internal virtual { + if (missingAccountFunds > 0) { + (bool success, ) = payable(msg.sender).call{value: missingAccountFunds}(""); + success; // Silence warning. The entrypoint should validate the result. + } + } + + /** + * @dev Ensures the caller is the {entrypoint}. + */ + function _checkEntryPoint() internal view virtual { + address sender = msg.sender; + if (sender != address(entryPoint())) { + revert AccountUnauthorized(sender); + } + } + + /** + * @dev Ensures the caller is the {entrypoint} or the account itself. + */ + function _checkEntryPointOrSelf() internal view virtual { + address sender = msg.sender; + if (sender != address(this) && sender != address(entryPoint())) { + revert AccountUnauthorized(sender); + } + } + + /** + * @dev Receive Ether. + */ + receive() external payable virtual {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/account/extensions/draft-AccountERC7579.sol b/dependencies/@openzeppelin-contracts-5.4.0/account/extensions/draft-AccountERC7579.sol new file mode 100644 index 00000000..40ea71ed --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/account/extensions/draft-AccountERC7579.sol @@ -0,0 +1,405 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (account/extensions/draft-AccountERC7579.sol) + +pragma solidity ^0.8.26; + +import {PackedUserOperation} from "../../interfaces/draft-IERC4337.sol"; +import {IERC1271} from "../../interfaces/IERC1271.sol"; +import {IERC7579Module, IERC7579Validator, IERC7579Execution, IERC7579AccountConfig, IERC7579ModuleConfig, MODULE_TYPE_VALIDATOR, MODULE_TYPE_EXECUTOR, MODULE_TYPE_FALLBACK} from "../../interfaces/draft-IERC7579.sol"; +import {ERC7579Utils, Mode, CallType, ExecType} from "../../account/utils/draft-ERC7579Utils.sol"; +import {EnumerableSet} from "../../utils/structs/EnumerableSet.sol"; +import {Bytes} from "../../utils/Bytes.sol"; +import {Packing} from "../../utils/Packing.sol"; +import {Address} from "../../utils/Address.sol"; +import {Calldata} from "../../utils/Calldata.sol"; +import {Account} from "../Account.sol"; + +/** + * @dev Extension of {Account} that implements support for ERC-7579 modules. + * + * To comply with the ERC-1271 support requirement, this contract defers signature validation to + * installed validator modules by calling {IERC7579Validator-isValidSignatureWithSender}. + * + * This contract does not implement validation logic for user operations since this functionality + * is often delegated to self-contained validation modules. Developers must install a validator module + * upon initialization (or any other mechanism to enable execution from the account): + * + * ```solidity + * contract MyAccountERC7579 is AccountERC7579, Initializable { + * function initializeAccount(address validator, bytes calldata validatorData) public initializer { + * _installModule(MODULE_TYPE_VALIDATOR, validator, validatorData); + * } + * } + * ``` + * + * [NOTE] + * ==== + * * Hook support is not included. See {AccountERC7579Hooked} for a version that hooks to execution. + * * Validator selection, when verifying either ERC-1271 signature or ERC-4337 UserOperation is implemented in + * internal virtual functions {_extractUserOpValidator} and {_extractSignatureValidator}. Both are implemented + * following common practices. However, this part is not standardized in ERC-7579 (or in any follow-up ERC). Some + * accounts may want to override these internal functions. + * * When combined with {ERC7739}, resolution ordering of {isValidSignature} may have an impact ({ERC7739} does not + * call super). Manual resolution might be necessary. + * * Static calls (using callType `0xfe`) are currently NOT supported. + * ==== + * + * WARNING: Removing all validator modules will render the account inoperable, as no user operations can be validated thereafter. + */ +abstract contract AccountERC7579 is Account, IERC1271, IERC7579Execution, IERC7579AccountConfig, IERC7579ModuleConfig { + using Bytes for *; + using ERC7579Utils for *; + using EnumerableSet for *; + using Packing for bytes32; + + EnumerableSet.AddressSet private _validators; + EnumerableSet.AddressSet private _executors; + mapping(bytes4 selector => address) private _fallbacks; + + /// @dev The account's {fallback} was called with a selector that doesn't have an installed handler. + error ERC7579MissingFallbackHandler(bytes4 selector); + + /// @dev Modifier that checks if the caller is an installed module of the given type. + modifier onlyModule(uint256 moduleTypeId, bytes calldata additionalContext) { + _checkModule(moduleTypeId, msg.sender, additionalContext); + _; + } + + /// @dev See {_fallback}. + fallback(bytes calldata) external payable virtual returns (bytes memory) { + return _fallback(); + } + + /// @inheritdoc IERC7579AccountConfig + function accountId() public view virtual returns (string memory) { + // vendorname.accountname.semver + return "@openzeppelin/community-contracts.AccountERC7579.v0.0.0"; + } + + /** + * @inheritdoc IERC7579AccountConfig + * + * @dev Supported call types: + * * Single (`0x00`): A single transaction execution. + * * Batch (`0x01`): A batch of transactions execution. + * * Delegate (`0xff`): A delegate call execution. + * + * Supported exec types: + * * Default (`0x00`): Default execution type (revert on failure). + * * Try (`0x01`): Try execution type (emits ERC7579TryExecuteFail on failure). + */ + function supportsExecutionMode(bytes32 encodedMode) public view virtual returns (bool) { + (CallType callType, ExecType execType, , ) = Mode.wrap(encodedMode).decodeMode(); + return + (callType == ERC7579Utils.CALLTYPE_SINGLE || + callType == ERC7579Utils.CALLTYPE_BATCH || + callType == ERC7579Utils.CALLTYPE_DELEGATECALL) && + (execType == ERC7579Utils.EXECTYPE_DEFAULT || execType == ERC7579Utils.EXECTYPE_TRY); + } + + /** + * @inheritdoc IERC7579AccountConfig + * + * @dev Supported module types: + * + * * Validator: A module used during the validation phase to determine if a transaction is valid and + * should be executed on the account. + * * Executor: A module that can execute transactions on behalf of the smart account via a callback. + * * Fallback Handler: A module that can extend the fallback functionality of a smart account. + */ + function supportsModule(uint256 moduleTypeId) public view virtual returns (bool) { + return + moduleTypeId == MODULE_TYPE_VALIDATOR || + moduleTypeId == MODULE_TYPE_EXECUTOR || + moduleTypeId == MODULE_TYPE_FALLBACK; + } + + /// @inheritdoc IERC7579ModuleConfig + function installModule( + uint256 moduleTypeId, + address module, + bytes calldata initData + ) public virtual onlyEntryPointOrSelf { + _installModule(moduleTypeId, module, initData); + } + + /// @inheritdoc IERC7579ModuleConfig + function uninstallModule( + uint256 moduleTypeId, + address module, + bytes calldata deInitData + ) public virtual onlyEntryPointOrSelf { + _uninstallModule(moduleTypeId, module, deInitData); + } + + /// @inheritdoc IERC7579ModuleConfig + function isModuleInstalled( + uint256 moduleTypeId, + address module, + bytes calldata additionalContext + ) public view virtual returns (bool) { + if (moduleTypeId == MODULE_TYPE_VALIDATOR) return _validators.contains(module); + if (moduleTypeId == MODULE_TYPE_EXECUTOR) return _executors.contains(module); + if (moduleTypeId == MODULE_TYPE_FALLBACK) return _fallbacks[bytes4(additionalContext[0:4])] == module; + return false; + } + + /// @inheritdoc IERC7579Execution + function execute(bytes32 mode, bytes calldata executionCalldata) public payable virtual onlyEntryPointOrSelf { + _execute(Mode.wrap(mode), executionCalldata); + } + + /// @inheritdoc IERC7579Execution + function executeFromExecutor( + bytes32 mode, + bytes calldata executionCalldata + ) + public + payable + virtual + onlyModule(MODULE_TYPE_EXECUTOR, Calldata.emptyBytes()) + returns (bytes[] memory returnData) + { + return _execute(Mode.wrap(mode), executionCalldata); + } + + /** + * @dev Implement ERC-1271 through IERC7579Validator modules. If module based validation fails, fallback to + * "native" validation by the abstract signer. + * + * NOTE: when combined with {ERC7739}, resolution ordering may have an impact ({ERC7739} does not call super). + * Manual resolution might be necessary. + */ + function isValidSignature(bytes32 hash, bytes calldata signature) public view virtual returns (bytes4) { + // check signature length is enough for extraction + if (signature.length >= 20) { + (address module, bytes calldata innerSignature) = _extractSignatureValidator(signature); + // if module is not installed, skip + if (isModuleInstalled(MODULE_TYPE_VALIDATOR, module, Calldata.emptyBytes())) { + // try validation, skip any revert + try IERC7579Validator(module).isValidSignatureWithSender(msg.sender, hash, innerSignature) returns ( + bytes4 magic + ) { + return magic; + } catch {} + } + } + return bytes4(0xffffffff); + } + + /** + * @dev Validates a user operation with {_signableUserOpHash} and returns the validation data + * if the module specified by the first 20 bytes of the nonce key is installed. Falls back to + * {Account-_validateUserOp} otherwise. + * + * See {_extractUserOpValidator} for the module extraction logic. + */ + function _validateUserOp( + PackedUserOperation calldata userOp, + bytes32 userOpHash + ) internal virtual override returns (uint256) { + address module = _extractUserOpValidator(userOp); + return + isModuleInstalled(MODULE_TYPE_VALIDATOR, module, Calldata.emptyBytes()) + ? IERC7579Validator(module).validateUserOp(userOp, _signableUserOpHash(userOp, userOpHash)) + : super._validateUserOp(userOp, userOpHash); + } + + /** + * @dev ERC-7579 execution logic. See {supportsExecutionMode} for supported modes. + * + * Reverts if the call type is not supported. + */ + function _execute( + Mode mode, + bytes calldata executionCalldata + ) internal virtual returns (bytes[] memory returnData) { + (CallType callType, ExecType execType, , ) = mode.decodeMode(); + if (callType == ERC7579Utils.CALLTYPE_SINGLE) return executionCalldata.execSingle(execType); + if (callType == ERC7579Utils.CALLTYPE_BATCH) return executionCalldata.execBatch(execType); + if (callType == ERC7579Utils.CALLTYPE_DELEGATECALL) return executionCalldata.execDelegateCall(execType); + revert ERC7579Utils.ERC7579UnsupportedCallType(callType); + } + + /** + * @dev Installs a module of the given type with the given initialization data. + * + * For the fallback module type, the `initData` is expected to be the (packed) concatenation of a 4-byte + * selector and the rest of the data to be sent to the handler when calling {IERC7579Module-onInstall}. + * + * Requirements: + * + * * Module type must be supported. See {supportsModule}. Reverts with {ERC7579Utils-ERC7579UnsupportedModuleType}. + * * Module must be of the given type. Reverts with {ERC7579Utils-ERC7579MismatchedModuleTypeId}. + * * Module must not be already installed. Reverts with {ERC7579Utils-ERC7579AlreadyInstalledModule}. + * + * Emits a {IERC7579ModuleConfig-ModuleInstalled} event. + */ + function _installModule(uint256 moduleTypeId, address module, bytes memory initData) internal virtual { + require(supportsModule(moduleTypeId), ERC7579Utils.ERC7579UnsupportedModuleType(moduleTypeId)); + require( + IERC7579Module(module).isModuleType(moduleTypeId), + ERC7579Utils.ERC7579MismatchedModuleTypeId(moduleTypeId, module) + ); + + if (moduleTypeId == MODULE_TYPE_VALIDATOR) { + require(_validators.add(module), ERC7579Utils.ERC7579AlreadyInstalledModule(moduleTypeId, module)); + } else if (moduleTypeId == MODULE_TYPE_EXECUTOR) { + require(_executors.add(module), ERC7579Utils.ERC7579AlreadyInstalledModule(moduleTypeId, module)); + } else if (moduleTypeId == MODULE_TYPE_FALLBACK) { + bytes4 selector; + (selector, initData) = _decodeFallbackData(initData); + require( + _fallbacks[selector] == address(0), + ERC7579Utils.ERC7579AlreadyInstalledModule(moduleTypeId, module) + ); + _fallbacks[selector] = module; + } + + IERC7579Module(module).onInstall(initData); + emit ModuleInstalled(moduleTypeId, module); + } + + /** + * @dev Uninstalls a module of the given type with the given de-initialization data. + * + * For the fallback module type, the `deInitData` is expected to be the (packed) concatenation of a 4-byte + * selector and the rest of the data to be sent to the handler when calling {IERC7579Module-onUninstall}. + * + * Requirements: + * + * * Module must be already installed. Reverts with {ERC7579Utils-ERC7579UninstalledModule} otherwise. + */ + function _uninstallModule(uint256 moduleTypeId, address module, bytes memory deInitData) internal virtual { + require(supportsModule(moduleTypeId), ERC7579Utils.ERC7579UnsupportedModuleType(moduleTypeId)); + + if (moduleTypeId == MODULE_TYPE_VALIDATOR) { + require(_validators.remove(module), ERC7579Utils.ERC7579UninstalledModule(moduleTypeId, module)); + } else if (moduleTypeId == MODULE_TYPE_EXECUTOR) { + require(_executors.remove(module), ERC7579Utils.ERC7579UninstalledModule(moduleTypeId, module)); + } else if (moduleTypeId == MODULE_TYPE_FALLBACK) { + bytes4 selector; + (selector, deInitData) = _decodeFallbackData(deInitData); + require( + _fallbackHandler(selector) == module && module != address(0), + ERC7579Utils.ERC7579UninstalledModule(moduleTypeId, module) + ); + delete _fallbacks[selector]; + } + + IERC7579Module(module).onUninstall(deInitData); + emit ModuleUninstalled(moduleTypeId, module); + } + + /** + * @dev Fallback function that delegates the call to the installed handler for the given selector. + * + * Reverts with {ERC7579MissingFallbackHandler} if the handler is not installed. + * + * Calls the handler with the original `msg.sender` appended at the end of the calldata following + * the ERC-2771 format. + */ + function _fallback() internal virtual returns (bytes memory) { + address handler = _fallbackHandler(msg.sig); + require(handler != address(0), ERC7579MissingFallbackHandler(msg.sig)); + + // From https://eips.ethereum.org/EIPS/eip-7579#fallback[ERC-7579 specifications]: + // - MUST utilize ERC-2771 to add the original msg.sender to the calldata sent to the fallback handler + // - MUST use call to invoke the fallback handler + (bool success, bytes memory returndata) = handler.call{value: msg.value}( + abi.encodePacked(msg.data, msg.sender) + ); + + if (success) return returndata; + + assembly ("memory-safe") { + revert(add(returndata, 0x20), mload(returndata)) + } + } + + /// @dev Returns the fallback handler for the given selector. Returns `address(0)` if not installed. + function _fallbackHandler(bytes4 selector) internal view virtual returns (address) { + return _fallbacks[selector]; + } + + /// @dev Checks if the module is installed. Reverts if the module is not installed. + function _checkModule( + uint256 moduleTypeId, + address module, + bytes calldata additionalContext + ) internal view virtual { + require( + isModuleInstalled(moduleTypeId, module, additionalContext), + ERC7579Utils.ERC7579UninstalledModule(moduleTypeId, module) + ); + } + + /** + * @dev Extracts the nonce validator from the user operation. + * + * To construct a nonce key, set nonce as follows: + * + * ``` + * | | + * ``` + * NOTE: The default behavior of this function replicates the behavior of + * https://github.com/rhinestonewtf/safe7579/blob/bb29e8b1a66658790c4169e72608e27d220f79be/src/Safe7579.sol#L266[Safe adapter], + * https://github.com/etherspot/etherspot-prime-contracts/blob/cfcdb48c4172cea0d66038324c0bae3288aa8caa/src/modular-etherspot-wallet/wallet/ModularEtherspotWallet.sol#L227[Etherspot's Prime Account], and + * https://github.com/erc7579/erc7579-implementation/blob/16138d1afd4e9711f6c1425133538837bd7787b5/src/MSAAdvanced.sol#L247[ERC7579 reference implementation]. + * + * This is not standardized in ERC-7579 (or in any follow-up ERC). Some accounts may want to override these internal functions. + * + * For example, https://github.com/bcnmy/nexus/blob/54f4e19baaff96081a8843672977caf712ef19f4/contracts/lib/NonceLib.sol#L17[Biconomy's Nexus] + * uses a similar yet incompatible approach (the validator address is also part of the nonce, but not at the same location) + */ + function _extractUserOpValidator(PackedUserOperation calldata userOp) internal pure virtual returns (address) { + return address(bytes32(userOp.nonce).extract_32_20(0)); + } + + /** + * @dev Extracts the signature validator from the signature. + * + * To construct a signature, set the first 20 bytes as the module address and the remaining bytes as the + * signature data: + * + * ``` + * | + * ``` + * + * NOTE: The default behavior of this function replicates the behavior of + * https://github.com/rhinestonewtf/safe7579/blob/bb29e8b1a66658790c4169e72608e27d220f79be/src/Safe7579.sol#L350[Safe adapter], + * https://github.com/bcnmy/nexus/blob/54f4e19baaff96081a8843672977caf712ef19f4/contracts/Nexus.sol#L239[Biconomy's Nexus], + * https://github.com/etherspot/etherspot-prime-contracts/blob/cfcdb48c4172cea0d66038324c0bae3288aa8caa/src/modular-etherspot-wallet/wallet/ModularEtherspotWallet.sol#L252[Etherspot's Prime Account], and + * https://github.com/erc7579/erc7579-implementation/blob/16138d1afd4e9711f6c1425133538837bd7787b5/src/MSAAdvanced.sol#L296[ERC7579 reference implementation]. + * + * This is not standardized in ERC-7579 (or in any follow-up ERC). Some accounts may want to override these internal functions. + */ + function _extractSignatureValidator( + bytes calldata signature + ) internal pure virtual returns (address module, bytes calldata innerSignature) { + return (address(bytes20(signature[0:20])), signature[20:]); + } + + /** + * @dev Extract the function selector from initData/deInitData for MODULE_TYPE_FALLBACK + * + * NOTE: If we had calldata here, we could use calldata slice which are cheaper to manipulate and don't require + * actual copy. However, this would require `_installModule` to get a calldata bytes object instead of a memory + * bytes object. This would prevent calling `_installModule` from a contract constructor and would force the use + * of external initializers. That may change in the future, as most accounts will probably be deployed as + * clones/proxy/ERC-7702 delegates and therefore rely on initializers anyway. + */ + function _decodeFallbackData( + bytes memory data + ) internal pure virtual returns (bytes4 selector, bytes memory remaining) { + return (bytes4(data), data.slice(4)); + } + + /// @dev By default, only use the modules for validation of userOp and signature. Disable raw signatures. + function _rawSignatureValidation( + bytes32 /*hash*/, + bytes calldata /*signature*/ + ) internal view virtual override returns (bool) { + return false; + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/account/extensions/draft-AccountERC7579Hooked.sol b/dependencies/@openzeppelin-contracts-5.4.0/account/extensions/draft-AccountERC7579Hooked.sol new file mode 100644 index 00000000..c83f38f5 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/account/extensions/draft-AccountERC7579Hooked.sol @@ -0,0 +1,107 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (account/extensions/draft-AccountERC7579Hooked.sol) + +pragma solidity ^0.8.26; + +import {IERC7579Hook, MODULE_TYPE_HOOK} from "../../interfaces/draft-IERC7579.sol"; +import {ERC7579Utils, Mode} from "../../account/utils/draft-ERC7579Utils.sol"; +import {AccountERC7579} from "./draft-AccountERC7579.sol"; + +/** + * @dev Extension of {AccountERC7579} with support for a single hook module (type 4). + * + * If installed, this extension will call the hook module's {IERC7579Hook-preCheck} before executing any operation + * with {_execute} (including {execute} and {executeFromExecutor} by default) and {IERC7579Hook-postCheck} thereafter. + * + * NOTE: Hook modules break the check-effect-interaction pattern. In particular, the {IERC7579Hook-preCheck} hook can + * lead to potentially dangerous reentrancy. Using the `withHook()` modifier is safe if no effect is performed + * before the preHook or after the postHook. That is the case on all functions here, but it may not be the case if + * functions that have this modifier are overridden. Developers should be extremely careful when implementing hook + * modules or further overriding functions that involve hooks. + */ +abstract contract AccountERC7579Hooked is AccountERC7579 { + address private _hook; + + /// @dev A hook module is already present. This contract only supports one hook module. + error ERC7579HookModuleAlreadyPresent(address hook); + + /** + * @dev Calls {IERC7579Hook-preCheck} before executing the modified function and {IERC7579Hook-postCheck} + * thereafter. + */ + modifier withHook() { + address hook_ = hook(); + bytes memory hookData; + + // slither-disable-next-line reentrancy-no-eth + if (hook_ != address(0)) hookData = IERC7579Hook(hook_).preCheck(msg.sender, msg.value, msg.data); + _; + if (hook_ != address(0)) IERC7579Hook(hook_).postCheck(hookData); + } + + /// @inheritdoc AccountERC7579 + function accountId() public view virtual override returns (string memory) { + // vendorname.accountname.semver + return "@openzeppelin/community-contracts.AccountERC7579Hooked.v0.0.0"; + } + + /// @dev Returns the hook module address if installed, or `address(0)` otherwise. + function hook() public view virtual returns (address) { + return _hook; + } + + /// @dev Supports hook modules. See {AccountERC7579-supportsModule} + function supportsModule(uint256 moduleTypeId) public view virtual override returns (bool) { + return moduleTypeId == MODULE_TYPE_HOOK || super.supportsModule(moduleTypeId); + } + + /// @inheritdoc AccountERC7579 + function isModuleInstalled( + uint256 moduleTypeId, + address module, + bytes calldata data + ) public view virtual override returns (bool) { + return + (moduleTypeId == MODULE_TYPE_HOOK && module == hook()) || + super.isModuleInstalled(moduleTypeId, module, data); + } + + /// @dev Installs a module with support for hook modules. See {AccountERC7579-_installModule} + function _installModule( + uint256 moduleTypeId, + address module, + bytes memory initData + ) internal virtual override withHook { + if (moduleTypeId == MODULE_TYPE_HOOK) { + require(_hook == address(0), ERC7579HookModuleAlreadyPresent(_hook)); + _hook = module; + } + super._installModule(moduleTypeId, module, initData); + } + + /// @dev Uninstalls a module with support for hook modules. See {AccountERC7579-_uninstallModule} + function _uninstallModule( + uint256 moduleTypeId, + address module, + bytes memory deInitData + ) internal virtual override withHook { + if (moduleTypeId == MODULE_TYPE_HOOK) { + require(_hook == module, ERC7579Utils.ERC7579UninstalledModule(moduleTypeId, module)); + _hook = address(0); + } + super._uninstallModule(moduleTypeId, module, deInitData); + } + + /// @dev Hooked version of {AccountERC7579-_execute}. + function _execute( + Mode mode, + bytes calldata executionCalldata + ) internal virtual override withHook returns (bytes[] memory) { + return super._execute(mode, executionCalldata); + } + + /// @dev Hooked version of {AccountERC7579-_fallback}. + function _fallback() internal virtual override withHook returns (bytes memory) { + return super._fallback(); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/account/extensions/draft-ERC7821.sol b/dependencies/@openzeppelin-contracts-5.4.0/account/extensions/draft-ERC7821.sol new file mode 100644 index 00000000..a8f22361 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/account/extensions/draft-ERC7821.sol @@ -0,0 +1,70 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (account/extensions/draft-ERC7821.sol) + +pragma solidity ^0.8.20; + +import {ERC7579Utils, Mode, CallType, ExecType, ModeSelector} from "../utils/draft-ERC7579Utils.sol"; +import {IERC7821} from "../../interfaces/draft-IERC7821.sol"; +import {Account} from "../Account.sol"; + +/** + * @dev Minimal batch executor following ERC-7821. + * + * Only supports supports single batch mode (`0x01000000000000000000`). Does not support optional "opData". + * + * @custom:stateless + */ +abstract contract ERC7821 is IERC7821 { + using ERC7579Utils for *; + + error UnsupportedExecutionMode(); + + /** + * @dev Executes the calls in `executionData` with no optional `opData` support. + * + * NOTE: Access to this function is controlled by {_erc7821AuthorizedExecutor}. Changing access permissions, for + * example to approve calls by the ERC-4337 entrypoint, should be implemented by overriding it. + * + * Reverts and bubbles up error if any call fails. + */ + function execute(bytes32 mode, bytes calldata executionData) public payable virtual { + if (!_erc7821AuthorizedExecutor(msg.sender, mode, executionData)) + revert Account.AccountUnauthorized(msg.sender); + if (!supportsExecutionMode(mode)) revert UnsupportedExecutionMode(); + executionData.execBatch(ERC7579Utils.EXECTYPE_DEFAULT); + } + + /// @inheritdoc IERC7821 + function supportsExecutionMode(bytes32 mode) public view virtual returns (bool result) { + (CallType callType, ExecType execType, ModeSelector modeSelector, ) = Mode.wrap(mode).decodeMode(); + return + callType == ERC7579Utils.CALLTYPE_BATCH && + execType == ERC7579Utils.EXECTYPE_DEFAULT && + modeSelector == ModeSelector.wrap(0x00000000); + } + + /** + * @dev Access control mechanism for the {execute} function. + * By default, only the contract itself is allowed to execute. + * + * Override this function to implement custom access control, for example to allow the + * ERC-4337 entrypoint to execute. + * + * ```solidity + * function _erc7821AuthorizedExecutor( + * address caller, + * bytes32 mode, + * bytes calldata executionData + * ) internal view virtual override returns (bool) { + * return caller == address(entryPoint()) || super._erc7821AuthorizedExecutor(caller, mode, executionData); + * } + * ``` + */ + function _erc7821AuthorizedExecutor( + address caller, + bytes32 /* mode */, + bytes calldata /* executionData */ + ) internal view virtual returns (bool) { + return caller == address(this); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/account/utils/EIP7702Utils.sol b/dependencies/@openzeppelin-contracts-5.4.0/account/utils/EIP7702Utils.sol new file mode 100644 index 00000000..804d6c2c --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/account/utils/EIP7702Utils.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (account/utils/EIP7702Utils.sol) + +pragma solidity ^0.8.20; + +/** + * @dev Library with common EIP-7702 utility functions. + * + * See https://eips.ethereum.org/EIPS/eip-7702[ERC-7702]. + */ +library EIP7702Utils { + bytes3 internal constant EIP7702_PREFIX = 0xef0100; + + /** + * @dev Returns the address of the delegate if `account` as an EIP-7702 delegation setup, or address(0) otherwise. + */ + function fetchDelegate(address account) internal view returns (address) { + bytes23 delegation = bytes23(account.code); + return bytes3(delegation) == EIP7702_PREFIX ? address(bytes20(delegation << 24)) : address(0); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/account/utils/draft-ERC4337Utils.sol b/dependencies/@openzeppelin-contracts-5.4.0/account/utils/draft-ERC4337Utils.sol new file mode 100644 index 00000000..6d2c8ccc --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/account/utils/draft-ERC4337Utils.sol @@ -0,0 +1,159 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.3.0) (account/utils/draft-ERC4337Utils.sol) + +pragma solidity ^0.8.20; + +import {IEntryPoint, PackedUserOperation} from "../../interfaces/draft-IERC4337.sol"; +import {Math} from "../../utils/math/Math.sol"; +import {Calldata} from "../../utils/Calldata.sol"; +import {Packing} from "../../utils/Packing.sol"; + +/// @dev This is available on all entrypoint since v0.4.0, but is not formally part of the ERC. +interface IEntryPointExtra { + function getUserOpHash(PackedUserOperation calldata userOp) external view returns (bytes32); +} + +/** + * @dev Library with common ERC-4337 utility functions. + * + * See https://eips.ethereum.org/EIPS/eip-4337[ERC-4337]. + */ +library ERC4337Utils { + using Packing for *; + + /// @dev Address of the entrypoint v0.7.0 + IEntryPoint internal constant ENTRYPOINT_V07 = IEntryPoint(0x0000000071727De22E5E9d8BAf0edAc6f37da032); + + /// @dev Address of the entrypoint v0.8.0 + IEntryPoint internal constant ENTRYPOINT_V08 = IEntryPoint(0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108); + + /// @dev For simulation purposes, validateUserOp (and validatePaymasterUserOp) return this value on success. + uint256 internal constant SIG_VALIDATION_SUCCESS = 0; + + /// @dev For simulation purposes, validateUserOp (and validatePaymasterUserOp) must return this value in case of signature failure, instead of revert. + uint256 internal constant SIG_VALIDATION_FAILED = 1; + + /// @dev Parses the validation data into its components. See {packValidationData}. + function parseValidationData( + uint256 validationData + ) internal pure returns (address aggregator, uint48 validAfter, uint48 validUntil) { + validAfter = uint48(bytes32(validationData).extract_32_6(0)); + validUntil = uint48(bytes32(validationData).extract_32_6(6)); + aggregator = address(bytes32(validationData).extract_32_20(12)); + if (validUntil == 0) validUntil = type(uint48).max; + } + + /// @dev Packs the validation data into a single uint256. See {parseValidationData}. + function packValidationData( + address aggregator, + uint48 validAfter, + uint48 validUntil + ) internal pure returns (uint256) { + return uint256(bytes6(validAfter).pack_6_6(bytes6(validUntil)).pack_12_20(bytes20(aggregator))); + } + + /// @dev Same as {packValidationData}, but with a boolean signature success flag. + function packValidationData(bool sigSuccess, uint48 validAfter, uint48 validUntil) internal pure returns (uint256) { + return + packValidationData( + address(uint160(Math.ternary(sigSuccess, SIG_VALIDATION_SUCCESS, SIG_VALIDATION_FAILED))), + validAfter, + validUntil + ); + } + + /** + * @dev Combines two validation data into a single one. + * + * The `aggregator` is set to {SIG_VALIDATION_SUCCESS} if both are successful, while + * the `validAfter` is the maximum and the `validUntil` is the minimum of both. + */ + function combineValidationData(uint256 validationData1, uint256 validationData2) internal pure returns (uint256) { + (address aggregator1, uint48 validAfter1, uint48 validUntil1) = parseValidationData(validationData1); + (address aggregator2, uint48 validAfter2, uint48 validUntil2) = parseValidationData(validationData2); + + bool success = aggregator1 == address(uint160(SIG_VALIDATION_SUCCESS)) && + aggregator2 == address(uint160(SIG_VALIDATION_SUCCESS)); + uint48 validAfter = uint48(Math.max(validAfter1, validAfter2)); + uint48 validUntil = uint48(Math.min(validUntil1, validUntil2)); + return packValidationData(success, validAfter, validUntil); + } + + /// @dev Returns the aggregator of the `validationData` and whether it is out of time range. + function getValidationData(uint256 validationData) internal view returns (address aggregator, bool outOfTimeRange) { + (address aggregator_, uint48 validAfter, uint48 validUntil) = parseValidationData(validationData); + return (aggregator_, block.timestamp < validAfter || validUntil < block.timestamp); + } + + /// @dev Get the hash of a user operation for a given entrypoint + function hash(PackedUserOperation calldata self, address entrypoint) internal view returns (bytes32) { + // NOTE: getUserOpHash is available since v0.4.0 + // + // Prior to v0.8.0, this was easy to replicate for any entrypoint and chainId. Since v0.8.0 of the + // entrypoint, this depends on the Entrypoint's domain separator, which cannot be hardcoded and is complex + // to recompute. Domain separator could be fetch using the `getDomainSeparatorV4` getter, or recomputed from + // the ERC-5267 getter, but both operation would require doing a view call to the entrypoint. Overall it feels + // simpler and less error prone to get that functionality from the entrypoint directly. + return IEntryPointExtra(entrypoint).getUserOpHash(self); + } + + /// @dev Returns `factory` from the {PackedUserOperation}, or address(0) if the initCode is empty or not properly formatted. + function factory(PackedUserOperation calldata self) internal pure returns (address) { + return self.initCode.length < 20 ? address(0) : address(bytes20(self.initCode[0:20])); + } + + /// @dev Returns `factoryData` from the {PackedUserOperation}, or empty bytes if the initCode is empty or not properly formatted. + function factoryData(PackedUserOperation calldata self) internal pure returns (bytes calldata) { + return self.initCode.length < 20 ? Calldata.emptyBytes() : self.initCode[20:]; + } + + /// @dev Returns `verificationGasLimit` from the {PackedUserOperation}. + function verificationGasLimit(PackedUserOperation calldata self) internal pure returns (uint256) { + return uint128(self.accountGasLimits.extract_32_16(0)); + } + + /// @dev Returns `callGasLimit` from the {PackedUserOperation}. + function callGasLimit(PackedUserOperation calldata self) internal pure returns (uint256) { + return uint128(self.accountGasLimits.extract_32_16(16)); + } + + /// @dev Returns the first section of `gasFees` from the {PackedUserOperation}. + function maxPriorityFeePerGas(PackedUserOperation calldata self) internal pure returns (uint256) { + return uint128(self.gasFees.extract_32_16(0)); + } + + /// @dev Returns the second section of `gasFees` from the {PackedUserOperation}. + function maxFeePerGas(PackedUserOperation calldata self) internal pure returns (uint256) { + return uint128(self.gasFees.extract_32_16(16)); + } + + /// @dev Returns the total gas price for the {PackedUserOperation} (ie. `maxFeePerGas` or `maxPriorityFeePerGas + basefee`). + function gasPrice(PackedUserOperation calldata self) internal view returns (uint256) { + unchecked { + // Following values are "per gas" + uint256 maxPriorityFee = maxPriorityFeePerGas(self); + uint256 maxFee = maxFeePerGas(self); + return Math.min(maxFee, maxPriorityFee + block.basefee); + } + } + + /// @dev Returns the first section of `paymasterAndData` from the {PackedUserOperation}. + function paymaster(PackedUserOperation calldata self) internal pure returns (address) { + return self.paymasterAndData.length < 52 ? address(0) : address(bytes20(self.paymasterAndData[0:20])); + } + + /// @dev Returns the second section of `paymasterAndData` from the {PackedUserOperation}. + function paymasterVerificationGasLimit(PackedUserOperation calldata self) internal pure returns (uint256) { + return self.paymasterAndData.length < 52 ? 0 : uint128(bytes16(self.paymasterAndData[20:36])); + } + + /// @dev Returns the third section of `paymasterAndData` from the {PackedUserOperation}. + function paymasterPostOpGasLimit(PackedUserOperation calldata self) internal pure returns (uint256) { + return self.paymasterAndData.length < 52 ? 0 : uint128(bytes16(self.paymasterAndData[36:52])); + } + + /// @dev Returns the fourth section of `paymasterAndData` from the {PackedUserOperation}. + function paymasterData(PackedUserOperation calldata self) internal pure returns (bytes calldata) { + return self.paymasterAndData.length < 52 ? Calldata.emptyBytes() : self.paymasterAndData[52:]; + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/account/utils/draft-ERC7579Utils.sol b/dependencies/@openzeppelin-contracts-5.4.0/account/utils/draft-ERC7579Utils.sol new file mode 100644 index 00000000..3e6544e6 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/account/utils/draft-ERC7579Utils.sol @@ -0,0 +1,280 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (account/utils/draft-ERC7579Utils.sol) + +pragma solidity ^0.8.20; + +import {Execution} from "../../interfaces/draft-IERC7579.sol"; +import {Packing} from "../../utils/Packing.sol"; +import {Address} from "../../utils/Address.sol"; + +type Mode is bytes32; +type CallType is bytes1; +type ExecType is bytes1; +type ModeSelector is bytes4; +type ModePayload is bytes22; + +/** + * @dev Library with common ERC-7579 utility functions. + * + * See https://eips.ethereum.org/EIPS/eip-7579[ERC-7579]. + */ +// slither-disable-next-line unused-state +library ERC7579Utils { + using Packing for *; + + /// @dev A single `call` execution. + CallType internal constant CALLTYPE_SINGLE = CallType.wrap(0x00); + + /// @dev A batch of `call` executions. + CallType internal constant CALLTYPE_BATCH = CallType.wrap(0x01); + + /// @dev A `delegatecall` execution. + CallType internal constant CALLTYPE_DELEGATECALL = CallType.wrap(0xFF); + + /// @dev Default execution type that reverts on failure. + ExecType internal constant EXECTYPE_DEFAULT = ExecType.wrap(0x00); + + /// @dev Execution type that does not revert on failure. + ExecType internal constant EXECTYPE_TRY = ExecType.wrap(0x01); + + /** + * @dev Emits when an {EXECTYPE_TRY} execution fails. + * @param batchExecutionIndex The index of the failed call in the execution batch. + * @param returndata The returned data from the failed call. + */ + event ERC7579TryExecuteFail(uint256 batchExecutionIndex, bytes returndata); + + /// @dev The provided {CallType} is not supported. + error ERC7579UnsupportedCallType(CallType callType); + + /// @dev The provided {ExecType} is not supported. + error ERC7579UnsupportedExecType(ExecType execType); + + /// @dev The provided module doesn't match the provided module type. + error ERC7579MismatchedModuleTypeId(uint256 moduleTypeId, address module); + + /// @dev The module is not installed. + error ERC7579UninstalledModule(uint256 moduleTypeId, address module); + + /// @dev The module is already installed. + error ERC7579AlreadyInstalledModule(uint256 moduleTypeId, address module); + + /// @dev The module type is not supported. + error ERC7579UnsupportedModuleType(uint256 moduleTypeId); + + /// @dev Input calldata not properly formatted and possibly malicious. + error ERC7579DecodingError(); + + /// @dev Executes a single call. + function execSingle( + bytes calldata executionCalldata, + ExecType execType + ) internal returns (bytes[] memory returnData) { + (address target, uint256 value, bytes calldata callData) = decodeSingle(executionCalldata); + returnData = new bytes[](1); + returnData[0] = _call(0, execType, target, value, callData); + } + + /// @dev Executes a batch of calls. + function execBatch( + bytes calldata executionCalldata, + ExecType execType + ) internal returns (bytes[] memory returnData) { + Execution[] calldata executionBatch = decodeBatch(executionCalldata); + returnData = new bytes[](executionBatch.length); + for (uint256 i = 0; i < executionBatch.length; ++i) { + returnData[i] = _call( + i, + execType, + executionBatch[i].target, + executionBatch[i].value, + executionBatch[i].callData + ); + } + } + + /// @dev Executes a delegate call. + function execDelegateCall( + bytes calldata executionCalldata, + ExecType execType + ) internal returns (bytes[] memory returnData) { + (address target, bytes calldata callData) = decodeDelegate(executionCalldata); + returnData = new bytes[](1); + returnData[0] = _delegatecall(0, execType, target, callData); + } + + /// @dev Encodes the mode with the provided parameters. See {decodeMode}. + function encodeMode( + CallType callType, + ExecType execType, + ModeSelector selector, + ModePayload payload + ) internal pure returns (Mode mode) { + return + Mode.wrap( + CallType + .unwrap(callType) + .pack_1_1(ExecType.unwrap(execType)) + .pack_2_4(bytes4(0)) + .pack_6_4(ModeSelector.unwrap(selector)) + .pack_10_22(ModePayload.unwrap(payload)) + ); + } + + /// @dev Decodes the mode into its parameters. See {encodeMode}. + function decodeMode( + Mode mode + ) internal pure returns (CallType callType, ExecType execType, ModeSelector selector, ModePayload payload) { + return ( + CallType.wrap(Packing.extract_32_1(Mode.unwrap(mode), 0)), + ExecType.wrap(Packing.extract_32_1(Mode.unwrap(mode), 1)), + ModeSelector.wrap(Packing.extract_32_4(Mode.unwrap(mode), 6)), + ModePayload.wrap(Packing.extract_32_22(Mode.unwrap(mode), 10)) + ); + } + + /// @dev Encodes a single call execution. See {decodeSingle}. + function encodeSingle( + address target, + uint256 value, + bytes calldata callData + ) internal pure returns (bytes memory executionCalldata) { + return abi.encodePacked(target, value, callData); + } + + /// @dev Decodes a single call execution. See {encodeSingle}. + function decodeSingle( + bytes calldata executionCalldata + ) internal pure returns (address target, uint256 value, bytes calldata callData) { + target = address(bytes20(executionCalldata[0:20])); + value = uint256(bytes32(executionCalldata[20:52])); + callData = executionCalldata[52:]; + } + + /// @dev Encodes a delegate call execution. See {decodeDelegate}. + function encodeDelegate( + address target, + bytes calldata callData + ) internal pure returns (bytes memory executionCalldata) { + return abi.encodePacked(target, callData); + } + + /// @dev Decodes a delegate call execution. See {encodeDelegate}. + function decodeDelegate( + bytes calldata executionCalldata + ) internal pure returns (address target, bytes calldata callData) { + target = address(bytes20(executionCalldata[0:20])); + callData = executionCalldata[20:]; + } + + /// @dev Encodes a batch of executions. See {decodeBatch}. + function encodeBatch(Execution[] memory executionBatch) internal pure returns (bytes memory executionCalldata) { + return abi.encode(executionBatch); + } + + /// @dev Decodes a batch of executions. See {encodeBatch}. + /// + /// NOTE: This function runs some checks and will throw a {ERC7579DecodingError} if the input is not properly formatted. + function decodeBatch(bytes calldata executionCalldata) internal pure returns (Execution[] calldata executionBatch) { + unchecked { + uint256 bufferLength = executionCalldata.length; + + // Check executionCalldata is not empty. + if (bufferLength < 32) revert ERC7579DecodingError(); + + // Get the offset of the array (pointer to the array length). + uint256 arrayLengthOffset = uint256(bytes32(executionCalldata[0:32])); + + // The array length (at arrayLengthOffset) should be 32 bytes long. We check that this is within the + // buffer bounds. Since we know bufferLength is at least 32, we can subtract with no overflow risk. + if (arrayLengthOffset > bufferLength - 32) revert ERC7579DecodingError(); + + // Get the array length. arrayLengthOffset + 32 is bounded by bufferLength so it does not overflow. + uint256 arrayLength = uint256(bytes32(executionCalldata[arrayLengthOffset:arrayLengthOffset + 32])); + + // Check that the buffer is long enough to store the array elements as "offset pointer": + // - each element of the array is an "offset pointer" to the data. + // - each "offset pointer" (to an array element) takes 32 bytes. + // - validity of the calldata at that location is checked when the array element is accessed, so we only + // need to check that the buffer is large enough to hold the pointers. + // + // Since we know bufferLength is at least arrayLengthOffset + 32, we can subtract with no overflow risk. + // Solidity limits length of such arrays to 2**64-1, this guarantees `arrayLength * 32` does not overflow. + if (arrayLength > type(uint64).max || bufferLength - arrayLengthOffset - 32 < arrayLength * 32) + revert ERC7579DecodingError(); + + assembly ("memory-safe") { + executionBatch.offset := add(add(executionCalldata.offset, arrayLengthOffset), 0x20) + executionBatch.length := arrayLength + } + } + } + + /// @dev Executes a `call` to the target with the provided {ExecType}. + function _call( + uint256 index, + ExecType execType, + address target, + uint256 value, + bytes calldata data + ) private returns (bytes memory) { + (bool success, bytes memory returndata) = (target == address(0) ? address(this) : target).call{value: value}( + data + ); + return _validateExecutionMode(index, execType, success, returndata); + } + + /// @dev Executes a `delegatecall` to the target with the provided {ExecType}. + function _delegatecall( + uint256 index, + ExecType execType, + address target, + bytes calldata data + ) private returns (bytes memory) { + (bool success, bytes memory returndata) = (target == address(0) ? address(this) : target).delegatecall(data); + return _validateExecutionMode(index, execType, success, returndata); + } + + /// @dev Validates the execution mode and returns the returndata. + function _validateExecutionMode( + uint256 index, + ExecType execType, + bool success, + bytes memory returndata + ) private returns (bytes memory) { + if (execType == ERC7579Utils.EXECTYPE_DEFAULT) { + Address.verifyCallResult(success, returndata); + } else if (execType == ERC7579Utils.EXECTYPE_TRY) { + if (!success) emit ERC7579TryExecuteFail(index, returndata); + } else { + revert ERC7579UnsupportedExecType(execType); + } + return returndata; + } +} + +// Operators +using {eqCallType as ==} for CallType global; +using {eqExecType as ==} for ExecType global; +using {eqModeSelector as ==} for ModeSelector global; +using {eqModePayload as ==} for ModePayload global; + +/// @dev Compares two `CallType` values for equality. +function eqCallType(CallType a, CallType b) pure returns (bool) { + return CallType.unwrap(a) == CallType.unwrap(b); +} + +/// @dev Compares two `ExecType` values for equality. +function eqExecType(ExecType a, ExecType b) pure returns (bool) { + return ExecType.unwrap(a) == ExecType.unwrap(b); +} + +/// @dev Compares two `ModeSelector` values for equality. +function eqModeSelector(ModeSelector a, ModeSelector b) pure returns (bool) { + return ModeSelector.unwrap(a) == ModeSelector.unwrap(b); +} + +/// @dev Compares two `ModePayload` values for equality. +function eqModePayload(ModePayload a, ModePayload b) pure returns (bool) { + return ModePayload.unwrap(a) == ModePayload.unwrap(b); +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/AbstractSigner.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/AbstractSigner.json new file mode 100644 index 00000000..3385a14b --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/AbstractSigner.json @@ -0,0 +1,10 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "AbstractSigner", + "sourceName": "contracts/utils/cryptography/signers/AbstractSigner.sol", + "abi": [], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/AccessControl.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/AccessControl.json new file mode 100644 index 00000000..44765e96 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/AccessControl.json @@ -0,0 +1,236 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "AccessControl", + "sourceName": "contracts/access/AccessControl.sol", + "abi": [ + { + "inputs": [], + "name": "AccessControlBadConfirmation", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "neededRole", + "type": "bytes32" + } + ], + "name": "AccessControlUnauthorizedAccount", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "callerConfirmation", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/AccessControlDefaultAdminRules.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/AccessControlDefaultAdminRules.json new file mode 100644 index 00000000..dbf10f03 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/AccessControlDefaultAdminRules.json @@ -0,0 +1,464 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "AccessControlDefaultAdminRules", + "sourceName": "contracts/access/extensions/AccessControlDefaultAdminRules.sol", + "abi": [ + { + "inputs": [], + "name": "AccessControlBadConfirmation", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint48", + "name": "schedule", + "type": "uint48" + } + ], + "name": "AccessControlEnforcedDefaultAdminDelay", + "type": "error" + }, + { + "inputs": [], + "name": "AccessControlEnforcedDefaultAdminRules", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "defaultAdmin", + "type": "address" + } + ], + "name": "AccessControlInvalidDefaultAdmin", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "neededRole", + "type": "bytes32" + } + ], + "name": "AccessControlUnauthorizedAccount", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "bits", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "SafeCastOverflowedUintDowncast", + "type": "error" + }, + { + "anonymous": false, + "inputs": [], + "name": "DefaultAdminDelayChangeCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint48", + "name": "newDelay", + "type": "uint48" + }, + { + "indexed": false, + "internalType": "uint48", + "name": "effectSchedule", + "type": "uint48" + } + ], + "name": "DefaultAdminDelayChangeScheduled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "DefaultAdminTransferCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "newAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint48", + "name": "acceptSchedule", + "type": "uint48" + } + ], + "name": "DefaultAdminTransferScheduled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptDefaultAdminTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "beginDefaultAdminTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "cancelDefaultAdminTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint48", + "name": "newDelay", + "type": "uint48" + } + ], + "name": "changeDefaultAdminDelay", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "defaultAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "defaultAdminDelay", + "outputs": [ + { + "internalType": "uint48", + "name": "", + "type": "uint48" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "defaultAdminDelayIncreaseWait", + "outputs": [ + { + "internalType": "uint48", + "name": "", + "type": "uint48" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingDefaultAdmin", + "outputs": [ + { + "internalType": "address", + "name": "newAdmin", + "type": "address" + }, + { + "internalType": "uint48", + "name": "schedule", + "type": "uint48" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingDefaultAdminDelay", + "outputs": [ + { + "internalType": "uint48", + "name": "newDelay", + "type": "uint48" + }, + { + "internalType": "uint48", + "name": "schedule", + "type": "uint48" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "rollbackDefaultAdminDelay", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/AccessControlEnumerable.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/AccessControlEnumerable.json new file mode 100644 index 00000000..df1c0988 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/AccessControlEnumerable.json @@ -0,0 +1,298 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "AccessControlEnumerable", + "sourceName": "contracts/access/extensions/AccessControlEnumerable.sol", + "abi": [ + { + "inputs": [], + "name": "AccessControlBadConfirmation", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "neededRole", + "type": "bytes32" + } + ], + "name": "AccessControlUnauthorizedAccount", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "getRoleMember", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleMemberCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleMembers", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "callerConfirmation", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/AccessManaged.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/AccessManaged.json new file mode 100644 index 00000000..aca13615 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/AccessManaged.json @@ -0,0 +1,101 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "AccessManaged", + "sourceName": "contracts/access/manager/AccessManaged.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "authority", + "type": "address" + } + ], + "name": "AccessManagedInvalidAuthority", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "internalType": "uint32", + "name": "delay", + "type": "uint32" + } + ], + "name": "AccessManagedRequiredDelay", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "caller", + "type": "address" + } + ], + "name": "AccessManagedUnauthorized", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "authority", + "type": "address" + } + ], + "name": "AuthorityUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "authority", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isConsumingScheduledOp", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newAuthority", + "type": "address" + } + ], + "name": "setAuthority", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/AccessManager.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/AccessManager.json new file mode 100644 index 00000000..87958641 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/AccessManager.json @@ -0,0 +1,1175 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "AccessManager", + "sourceName": "contracts/access/manager/AccessManager.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "initialAdmin", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "operationId", + "type": "bytes32" + } + ], + "name": "AccessManagerAlreadyScheduled", + "type": "error" + }, + { + "inputs": [], + "name": "AccessManagerBadConfirmation", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "operationId", + "type": "bytes32" + } + ], + "name": "AccessManagerExpired", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "initialAdmin", + "type": "address" + } + ], + "name": "AccessManagerInvalidInitialAdmin", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "roleId", + "type": "uint64" + } + ], + "name": "AccessManagerLockedRole", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "operationId", + "type": "bytes32" + } + ], + "name": "AccessManagerNotReady", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "operationId", + "type": "bytes32" + } + ], + "name": "AccessManagerNotScheduled", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "msgsender", + "type": "address" + }, + { + "internalType": "uint64", + "name": "roleId", + "type": "uint64" + } + ], + "name": "AccessManagerUnauthorizedAccount", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes4", + "name": "selector", + "type": "bytes4" + } + ], + "name": "AccessManagerUnauthorizedCall", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "msgsender", + "type": "address" + }, + { + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes4", + "name": "selector", + "type": "bytes4" + } + ], + "name": "AccessManagerUnauthorizedCancel", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "AccessManagerUnauthorizedConsume", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "AddressEmptyCode", + "type": "error" + }, + { + "inputs": [], + "name": "FailedCall", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + } + ], + "name": "InsufficientBalance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "bits", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "SafeCastOverflowedUintDowncast", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "operationId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "uint32", + "name": "nonce", + "type": "uint32" + } + ], + "name": "OperationCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "operationId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "uint32", + "name": "nonce", + "type": "uint32" + } + ], + "name": "OperationExecuted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "operationId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "uint32", + "name": "nonce", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint48", + "name": "schedule", + "type": "uint48" + }, + { + "indexed": false, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "OperationScheduled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "roleId", + "type": "uint64" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "admin", + "type": "uint64" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "roleId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "delay", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint48", + "name": "since", + "type": "uint48" + } + ], + "name": "RoleGrantDelayChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "roleId", + "type": "uint64" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "delay", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint48", + "name": "since", + "type": "uint48" + }, + { + "indexed": false, + "internalType": "bool", + "name": "newMember", + "type": "bool" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "roleId", + "type": "uint64" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "guardian", + "type": "uint64" + } + ], + "name": "RoleGuardianChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "roleId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "RoleLabel", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "roleId", + "type": "uint64" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "delay", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint48", + "name": "since", + "type": "uint48" + } + ], + "name": "TargetAdminDelayUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "closed", + "type": "bool" + } + ], + "name": "TargetClosed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes4", + "name": "selector", + "type": "bytes4" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "roleId", + "type": "uint64" + } + ], + "name": "TargetFunctionRoleUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "ADMIN_ROLE", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PUBLIC_ROLE", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes4", + "name": "selector", + "type": "bytes4" + } + ], + "name": "canCall", + "outputs": [ + { + "internalType": "bool", + "name": "immediate", + "type": "bool" + }, + { + "internalType": "uint32", + "name": "delay", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "cancel", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "consumeScheduledOp", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "execute", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "expiration", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "roleId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccess", + "outputs": [ + { + "internalType": "uint48", + "name": "since", + "type": "uint48" + }, + { + "internalType": "uint32", + "name": "currentDelay", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "pendingDelay", + "type": "uint32" + }, + { + "internalType": "uint48", + "name": "effect", + "type": "uint48" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "getNonce", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "roleId", + "type": "uint64" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "roleId", + "type": "uint64" + } + ], + "name": "getRoleGrantDelay", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "roleId", + "type": "uint64" + } + ], + "name": "getRoleGuardian", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "getSchedule", + "outputs": [ + { + "internalType": "uint48", + "name": "", + "type": "uint48" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "getTargetAdminDelay", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes4", + "name": "selector", + "type": "bytes4" + } + ], + "name": "getTargetFunctionRole", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "roleId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint32", + "name": "executionDelay", + "type": "uint32" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "roleId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "isMember", + "type": "bool" + }, + { + "internalType": "uint32", + "name": "executionDelay", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "hashOperation", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "isTargetClosed", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "roleId", + "type": "uint64" + }, + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "labelRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "minSetback", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "data", + "type": "bytes[]" + } + ], + "name": "multicall", + "outputs": [ + { + "internalType": "bytes[]", + "name": "results", + "type": "bytes[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "roleId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "callerConfirmation", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "roleId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "uint48", + "name": "when", + "type": "uint48" + } + ], + "name": "schedule", + "outputs": [ + { + "internalType": "bytes32", + "name": "operationId", + "type": "bytes32" + }, + { + "internalType": "uint32", + "name": "nonce", + "type": "uint32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "roleId", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "newDelay", + "type": "uint32" + } + ], + "name": "setGrantDelay", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "roleId", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "admin", + "type": "uint64" + } + ], + "name": "setRoleAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "roleId", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "guardian", + "type": "uint64" + } + ], + "name": "setRoleGuardian", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint32", + "name": "newDelay", + "type": "uint32" + } + ], + "name": "setTargetAdminDelay", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bool", + "name": "closed", + "type": "bool" + } + ], + "name": "setTargetClosed", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes4[]", + "name": "selectors", + "type": "bytes4[]" + }, + { + "internalType": "uint64", + "name": "roleId", + "type": "uint64" + } + ], + "name": "setTargetFunctionRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "address", + "name": "newAuthority", + "type": "address" + } + ], + "name": "updateAuthority", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x608060405234801561000f575f5ffd5b50604051612cc8380380612cc883398101604081905261002e91610441565b6001600160a01b03811661005c57604051630409d6d160e11b81525f60048201526024015b60405180910390fd5b6100685f82818061006f565b50506104bc565b5f6002600160401b03196001600160401b038616016100ac5760405163061c6a4360e21b81526001600160401b0386166004820152602401610053565b6001600160401b0385165f9081526001602090815260408083206001600160a01b038816845290915281205465ffffffffffff16159081156101a15763ffffffff85166100f76102b5565b6101019190610482565b905060405180604001604052808265ffffffffffff1681526020016101318663ffffffff166102c460201b60201c565b6001600160701b039081169091526001600160401b0389165f9081526001602090815260408083206001600160a01b038c16845282529091208351815494909201519092166601000000000000026001600160a01b031990931665ffffffffffff90911617919091179055610247565b6001600160401b0387165f9081526001602090815260408083206001600160a01b038a1684529091528120546101ed9166010000000000009091046001600160701b03169086906102cd565b6001600160401b0389165f9081526001602090815260408083206001600160a01b038c168452909152902080546001600160701b03909316660100000000000002600160301b600160a01b03199093169290921790915590505b6040805163ffffffff8616815265ffffffffffff831660208201528315158183015290516001600160a01b038816916001600160401b038a16917ff98448b987f1428e0e230e1f3c6e2ce15b5693eaf31827fbd0b1ec4b424ae7cf9181900360600190a35095945050505050565b5f6102bf42610373565b905090565b63ffffffff1690565b5f80806102e26001600160701b0387166103a9565b90505f61031d8563ffffffff168763ffffffff168463ffffffff1611610308575f610312565b61031288856104a0565b63ffffffff166103c7565b905063ffffffff811661032e6102b5565b6103389190610482565b925063ffffffff8616602083901b67ffffffff0000000016604085901b6dffffffffffff000000000000000016171793505050935093915050565b5f65ffffffffffff8211156103a5576040516306dfcc6560e41b81526030600482015260248101839052604401610053565b5090565b5f806103bd6001600160701b0384166103d7565b5090949350505050565b8082118183180281185b92915050565b5f80806103eb846103e66102b5565b6103f8565b9250925092509193909250565b6001600160501b03602083901c166001600160701b03831665ffffffffffff604085901c811690841681111561043057828282610434565b815f5f5b9250925092509250925092565b5f60208284031215610451575f5ffd5b81516001600160a01b0381168114610467575f5ffd5b9392505050565b634e487b7160e01b5f52601160045260245ffd5b65ffffffffffff81811683821601908111156103d1576103d161046e565b63ffffffff82811682821603908111156103d1576103d161046e565b6127ff806104c95f395ff3fe6080604052600436106101db575f3560e01c80636d5115bd116100fd578063b700961311610092578063d22b598911610062578063d22b598914610636578063d6bb62c614610655578063f801a69814610674578063fe0776f5146106ad575f5ffd5b8063b7009613146105a8578063b7d2b162146105e3578063cc1b6c8114610602578063d1f856ee14610617575f5ffd5b8063a166aa89116100cd578063a166aa8914610501578063a64d95ce14610530578063abd9bd2a1461054f578063ac9650d81461057c575f5ffd5b80636d5115bd1461049157806375b238fc146104b0578063853551b8146104c357806394c7d7ee146104e2575f5ffd5b806330cae187116101735780634665096d116101435780634665096d146104035780634c1da1e2146104185780635296295214610437578063530dd45614610456575f5ffd5b806330cae1871461035c5780633adc277a1461037b5780633ca7c02a146103b15780634136a33c146103cb575f5ffd5b806318ff183c116101ae57806318ff183c146102b25780631cff79cd146102d157806325c471a0146102e45780633078f11414610303575f5ffd5b806308d6122d146101df5780630b0a93ba1461020057806312be87271461025f578063167bd39514610293575b5f5ffd5b3480156101ea575f5ffd5b506101fe6101f93660046120d9565b6106cc565b005b34801561020b575f5ffd5b5061024261021a36600461213b565b6001600160401b039081165f9081526001602081905260409091200154600160401b90041690565b6040516001600160401b0390911681526020015b60405180910390f35b34801561026a575f5ffd5b5061027e61027936600461213b565b61071e565b60405163ffffffff9091168152602001610256565b34801561029e575f5ffd5b506101fe6102ad366004612154565b610758565b3480156102bd575f5ffd5b506101fe6102cc36600461218f565b61076e565b61027e6102df3660046121f8565b6107d0565b3480156102ef575f5ffd5b506101fe6102fe36600461225b565b6108fc565b34801561030e575f5ffd5b5061032261031d36600461229d565b61091e565b604051610256949392919065ffffffffffff948516815263ffffffff93841660208201529190921660408201529116606082015260800190565b348015610367575f5ffd5b506101fe6103763660046122b7565b610982565b348015610386575f5ffd5b5061039a6103953660046122e8565b610994565b60405165ffffffffffff9091168152602001610256565b3480156103bc575f5ffd5b506102426001600160401b0381565b3480156103d6575f5ffd5b5061027e6103e53660046122e8565b5f90815260026020526040902054600160301b900463ffffffff1690565b34801561040e575f5ffd5b5062093a8061027e565b348015610423575f5ffd5b5061027e6104323660046122ff565b6109c5565b348015610442575f5ffd5b506101fe6104513660046122b7565b6109f2565b348015610461575f5ffd5b5061024261047036600461213b565b6001600160401b039081165f90815260016020819052604090912001541690565b34801561049c575f5ffd5b506102426104ab36600461232f565b610a04565b3480156104bb575f5ffd5b506102425f81565b3480156104ce575f5ffd5b506101fe6104dd36600461235b565b610a3e565b3480156104ed575f5ffd5b506101fe6104fc3660046121f8565b610ad5565b34801561050c575f5ffd5b5061052061051b3660046122ff565b610b7f565b6040519015158152602001610256565b34801561053b575f5ffd5b506101fe61054a366004612376565b610ba6565b34801561055a575f5ffd5b5061056e61056936600461239e565b610bb8565b604051908152602001610256565b348015610587575f5ffd5b5061059b6105963660046123fe565b610bf0565b604051610256919061243c565b3480156105b3575f5ffd5b506105c76105c23660046124c0565b610cd5565b60408051921515835263ffffffff909116602083015201610256565b3480156105ee575f5ffd5b506101fe6105fd36600461229d565b610d56565b34801561060d575f5ffd5b506206978061027e565b348015610622575f5ffd5b506105c761063136600461229d565b610d6d565b348015610641575f5ffd5b506101fe610650366004612508565b610de6565b348015610660575f5ffd5b5061027e61066f36600461239e565b610df8565b34801561067f575f5ffd5b5061069361068e366004612524565b610f4b565b6040805192835263ffffffff909116602083015201610256565b3480156106b8575f5ffd5b506101fe6106c736600461229d565b61108c565b6106d46110b5565b5f5b828110156107175761070f858585848181106106f4576106f4612591565b905060200201602081019061070991906125a5565b8461112c565b6001016106d6565b5050505050565b6001600160401b0381165f9081526001602081905260408220015461075290600160801b90046001600160701b03166111ad565b92915050565b6107606110b5565b61076a82826111cb565b5050565b6107766110b5565b604051637a9e5e4b60e01b81526001600160a01b038281166004830152831690637a9e5e4b906024015f604051808303815f87803b1580156107b6575f5ffd5b505af11580156107c8573d5f5f3e3d5ffd5b505050505050565b5f3381806107e08388888861123c565b91509150811580156107f6575063ffffffff8116155b15610849578287610807888861128d565b6040516381c6f24b60e01b81526001600160a01b0393841660048201529290911660248301526001600160e01b03191660448201526064015b60405180910390fd5b5f61085684898989610bb8565b90505f63ffffffff831615158061087c575061087182610994565b65ffffffffffff1615155b1561088d5761088a826112a4565b90505b6003546108a38a61089e8b8b61128d565b6113a2565b6003819055506108ea8a8a8a8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152503492506113e4915050565b506003559450505050505b9392505050565b6109046110b5565b61091883836109128661071e565b84611484565b50505050565b6001600160401b0382165f9081526001602090815260408083206001600160a01b03851684529091528120805465ffffffffffff81169291829182919061097490600160301b90046001600160701b03166116ca565b969991985096509350505050565b61098a6110b5565b61076a82826116eb565b5f8181526002602052604081205465ffffffffffff166109b38161178e565b6109bd57806108f5565b5f9392505050565b6001600160a01b0381165f90815260208190526040812060010154610752906001600160701b03166111ad565b6109fa6110b5565b61076a82826117bc565b6001600160a01b0382165f908152602081815260408083206001600160e01b0319851684529091529020546001600160401b031692915050565b610a466110b5565b6001600160401b0383161580610a6457506001600160401b03838116145b15610a8d5760405163061c6a4360e21b81526001600160401b0384166004820152602401610840565b826001600160401b03167f1256f5b5ecb89caec12db449738f2fbcd1ba5806cf38f35413f4e5c15bf6a4508383604051610ac89291906125e8565b60405180910390a2505050565b60408051638fb3603760e01b80825291513392918391638fb36037916004808201926020929091908290030181865afa158015610b14573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b389190612603565b6001600160e01b03191614610b6b57604051630641fee960e31b81526001600160a01b0382166004820152602401610840565b610717610b7a85838686610bb8565b6112a4565b6001600160a01b03165f90815260208190526040902060010154600160701b900460ff1690565b610bae6110b5565b61076a828261186d565b5f84848484604051602001610bd0949392919061261e565b604051602081830303815290604052805190602001209050949350505050565b604080515f815260208101909152606090826001600160401b03811115610c1957610c19612685565b604051908082528060200260200182016040528015610c4c57816020015b6060815260200190600190039081610c375790505b5091505f5b83811015610ccd57610ca830868684818110610c6f57610c6f612591565b9050602002810190610c819190612699565b85604051602001610c94939291906126f2565b60405160208183030381529060405261197c565b838281518110610cba57610cba612591565b6020908102919091010152600101610c51565b505092915050565b5f5f610ce084610b7f565b15610cef57505f905080610d4e565b306001600160a01b03861603610d1357610d0984846119ee565b5f91509150610d4e565b5f610d1e8585610a04565b90505f5f610d2c8389610d6d565b9150915081610d3c575f5f610d46565b63ffffffff811615815b945094505050505b935093915050565b610d5e6110b5565b610d688282611a04565b505050565b5f8067fffffffffffffffe196001600160401b03851601610d935750600190505f610ddf565b5f5f610d9f868661091e565b5050915091508165ffffffffffff165f14158015610dd45750610dc0611aed565b65ffffffffffff168265ffffffffffff1611155b93509150610ddf9050565b9250929050565b610dee6110b5565b61076a8282611afc565b5f3381610e05858561128d565b90505f610e1488888888610bb8565b5f8181526002602052604081205491925065ffffffffffff9091169003610e515760405163060a299b60e41b815260048101829052602401610840565b826001600160a01b0316886001600160a01b031614610eea575f610e755f85610d6d565b5090505f610e8f610e8961021a8b87610a04565b86610d6d565b50905081158015610e9e575080155b15610ee757604051630ff89d4760e21b81526001600160a01b038087166004830152808c1660248301528a1660448201526001600160e01b031985166064820152608401610840565b50505b5f81815260026020526040808220805465ffffffffffff1916908190559051600160301b90910463ffffffff1691829184917fbd9ac67a6e2f6463b80927326310338bcbb4bdb7936ce1365ea3e01067e7b9f791a398975050505050505050565b5f803381610f5b8289898961123c565b9150505f8163ffffffff16610f6e611aed565b610f789190612707565b905063ffffffff82161580610fae57505f8665ffffffffffff16118015610fae57508065ffffffffffff168665ffffffffffff16105b15610fbf5782896108078a8a61128d565b610fd98665ffffffffffff168265ffffffffffff16611bb7565b9550610fe7838a8a8a610bb8565b9450610ff285611bc6565b5f8581526002602052604090819020805465ffffffffffff891669ffffffffffffffffffff19821617600160301b9182900463ffffffff90811660010190811692830291909117909255915190955086907f82a2da5dee54ea8021c6545b4444620291e07ee83be6dd57edb175062715f3b490611078908a9088908f908f908f90612725565b60405180910390a350505094509492505050565b6001600160a01b0381163314610d5e57604051635f159e6360e01b815260040160405180910390fd5b335f806110c3838236611c12565b9150915081610d68578063ffffffff165f0361111d575f6110e48136611cd5565b5060405163f07e038f60e01b81526001600160a01b03871660048201526001600160401b03821660248201529092506044019050610840565b610918610b7a84305f36610bb8565b6001600160a01b0383165f818152602081815260408083206001600160e01b0319871680855290835292819020805467ffffffffffffffff19166001600160401b038716908117909155905192835292917f9ea6790c7dadfd01c9f8b9762b3682607af2c7e79e05a9f9fdf5580dde949151910160405180910390a3505050565b5f5f6111c1836001600160701b03166116ca565b5090949350505050565b6001600160a01b0382165f81815260208190526040908190206001018054841515600160701b0260ff60701b19909116179055517f90d4e7bb7e5d933792b3562e1741306f8be94837e1348dacef9b6f1df56eb1389061123090841515815260200190565b60405180910390a25050565b5f80306001600160a01b0386160361126257611259868585611c12565b91509150611284565b6004831061127e5761127986866105c2878761128d565b611259565b505f9050805b94509492505050565b5f61129b600482848661265e565b6108f59161276a565b5f8181526002602052604081205465ffffffffffff811690600160301b900463ffffffff168183036112ec5760405163060a299b60e41b815260048101859052602401610840565b6112f4611aed565b65ffffffffffff168265ffffffffffff16111561132757604051630c65b5bd60e11b815260048101859052602401610840565b6113308261178e565b1561135157604051631e2975b960e21b815260048101859052602401610840565b5f84815260026020526040808220805465ffffffffffff191690555163ffffffff83169186917f76a2a46953689d4861a5d3f6ed883ad7e6af674a21f8e162707159fc9dde614d9190a39392505050565b604080516001600160a01b03939093166020808501919091526001600160e01b0319929092168382015280518084038201815260609093019052815191012090565b6060814710156114105760405163cf47918160e01b815247600482015260248101839052604401610840565b5f5f856001600160a01b0316848660405161142b91906127a2565b5f6040518083038185875af1925050503d805f8114611465576040519150601f19603f3d011682016040523d82523d5f602084013e61146a565b606091505b509150915061147a868383611ebb565b9695505050505050565b5f67fffffffffffffffe196001600160401b038616016114c25760405163061c6a4360e21b81526001600160401b0386166004820152602401610840565b6001600160401b0385165f9081526001602090815260408083206001600160a01b038816845290915281205465ffffffffffff16159081156115b2578463ffffffff1661150d611aed565b6115179190612707565b905060405180604001604052808265ffffffffffff1681526020016115458663ffffffff1663ffffffff1690565b6001600160701b039081169091526001600160401b0389165f9081526001602090815260408083206001600160a01b038c1684528252909120835181549490920151909216600160301b026001600160a01b031990931665ffffffffffff9091161791909117905561165c565b6001600160401b0387165f9081526001602090815260408083206001600160a01b038a1684529091528120546115fb91600160301b9091046001600160701b0316908690611f17565b6001600160401b0389165f9081526001602090815260408083206001600160a01b038c168452909152902080546001600160701b03909316600160301b0273ffffffffffffffffffffffffffff000000000000199093169290921790915590505b6040805163ffffffff8616815265ffffffffffff831660208201528315158183015290516001600160a01b038816916001600160401b038a16917ff98448b987f1428e0e230e1f3c6e2ce15b5693eaf31827fbd0b1ec4b424ae7cf9181900360600190a35095945050505050565b5f5f5f6116de846116d9611aed565b611fbd565b9250925092509193909250565b6001600160401b038216158061170957506001600160401b03828116145b156117325760405163061c6a4360e21b81526001600160401b0383166004820152602401610840565b6001600160401b038281165f818152600160208190526040808320909101805467ffffffffffffffff19169486169485179055517f1fd6dd7631312dfac2205b52913f99de03b4d7e381d5d27d3dbfe0713e6e63409190a35050565b5f611797611aed565b65ffffffffffff166117ac62093a8084612707565b65ffffffffffff16111592915050565b6001600160401b03821615806117da57506001600160401b03828116145b156118035760405163061c6a4360e21b81526001600160401b0383166004820152602401610840565b6001600160401b038281165f81815260016020819052604080832090910180546fffffffffffffffff00000000000000001916600160401b958716958602179055517f7a8059630b897b5de4c08ade69f8b90c3ead1f8596d62d10b6c4d14a0afb4ae29190a35050565b67fffffffffffffffe196001600160401b038316016118aa5760405163061c6a4360e21b81526001600160401b0383166004820152602401610840565b6001600160401b0382165f908152600160208190526040822001546118e390600160801b90046001600160701b03168362069780611f17565b6001600160401b0385165f818152600160208190526040918290200180546001600160701b03909516600160801b026dffffffffffffffffffffffffffff60801b199095169490941790935591519092507ffeb69018ee8b8fd50ea86348f1267d07673379f72cffdeccec63853ee8ce8b4890610ac8908590859063ffffffff92909216825265ffffffffffff16602082015260400190565b60605f5f846001600160a01b03168460405161199891906127a2565b5f60405180830381855af49150503d805f81146119d0576040519150601f19603f3d011682016040523d82523d5f602084013e6119d5565b606091505b50915091506119e5858383611ebb565b95945050505050565b5f6119f983836113a2565b600354149392505050565b5f67fffffffffffffffe196001600160401b03841601611a425760405163061c6a4360e21b81526001600160401b0384166004820152602401610840565b6001600160401b0383165f9081526001602090815260408083206001600160a01b038616845290915281205465ffffffffffff169003611a8357505f610752565b6001600160401b0383165f8181526001602090815260408083206001600160a01b038716808552925280832080546001600160a01b0319169055519092917ff229baa593af28c41b1d16b748cd7688f0c83aaf92d4be41c44005defe84c16691a350600192915050565b5f611af742612009565b905090565b6001600160a01b0382165f90815260208190526040812060010154611b2e906001600160701b03168362069780611f17565b6001600160a01b0385165f818152602081815260409182902060010180546dffffffffffffffffffffffffffff19166001600160701b039690961695909517909455805163ffffffff8716815265ffffffffffff841694810194909452919350917fa56b76017453f399ec2327ba00375dbfb1fd070ff854341ad6191e6a2e2de19c9101610ac8565b5f8282188284110282186108f5565b5f8181526002602052604090205465ffffffffffff168015801590611bf15750611bef8161178e565b155b1561076a5760405163813e945960e01b815260048101839052602401610840565b5f806004831015611c2757505f905080610d4e565b306001600160a01b03861603611c4a57610d0930611c45868661128d565b6119ee565b5f5f5f611c578787611cd5565b92509250925082158015611c6f5750611c6f30610b7f565b15611c82575f5f94509450505050610d4e565b5f5f611c8e848b610d6d565b9150915081611ca7575f5f965096505050505050610d4e565b611cbd8363ffffffff168263ffffffff16611bb7565b63ffffffff8116159b909a5098505050505050505050565b5f80806004841015611cee57505f915081905080611eb4565b5f611cf9868661128d565b90506001600160e01b031981166310a6aa3760e31b1480611d2a57506001600160e01b031981166330cae18760e01b145b80611d4557506001600160e01b0319811663294b14a960e11b145b80611d6057506001600160e01b03198116635326cae760e11b145b80611d7b57506001600160e01b0319811663d22b598960e01b145b15611d905760015f5f93509350935050611eb4565b6001600160e01b0319811663063fc60f60e21b1480611dbf57506001600160e01b0319811663167bd39560e01b145b80611dda57506001600160e01b031981166308d6122d60e01b145b15611e19575f611dee60246004888a61265e565b810190611dfb91906122ff565b90505f611e07826109c5565b600196505f95509350611eb492505050565b6001600160e01b0319811663012e238d60e51b1480611e4857506001600160e01b03198116635be958b160e11b145b15611ea0575f611e5c60246004888a61265e565b810190611e69919061213b565b90506001611e92826001600160401b039081165f90815260016020819052604090912001541690565b5f9450945094505050611eb4565b5f611eab3083610a04565b5f935093509350505b9250925092565b606082611ed057611ecb8261203f565b6108f5565b8151158015611ee757506001600160a01b0384163b155b15611f1057604051639996b31560e01b81526001600160a01b0385166004820152602401610840565b50806108f5565b5f5f5f611f2c866001600160701b03166111ad565b90505f611f678563ffffffff168763ffffffff168463ffffffff1611611f52575f611f5c565b611f5c88856127ad565b63ffffffff16611bb7565b90508063ffffffff16611f78611aed565b611f829190612707565b925063ffffffff8616602083901b67ffffffff0000000016604085901b6dffffffffffff000000000000000016171793505050935093915050565b69ffffffffffffffffffff602083901c166001600160701b03831665ffffffffffff604085901c8116908416811115611ff857828282611ffc565b815f5f5b9250925092509250925092565b5f65ffffffffffff82111561203b576040516306dfcc6560e41b81526030600482015260248101839052604401610840565b5090565b80511561204e57805160208201fd5b60405163d6bda27560e01b815260040160405180910390fd5b50565b6001600160a01b0381168114612067575f5ffd5b5f5f83601f84011261208e575f5ffd5b5081356001600160401b038111156120a4575f5ffd5b6020830191508360208260051b8501011115610ddf575f5ffd5b80356001600160401b03811681146120d4575f5ffd5b919050565b5f5f5f5f606085870312156120ec575f5ffd5b84356120f78161206a565b935060208501356001600160401b03811115612111575f5ffd5b61211d8782880161207e565b90945092506121309050604086016120be565b905092959194509250565b5f6020828403121561214b575f5ffd5b6108f5826120be565b5f5f60408385031215612165575f5ffd5b82356121708161206a565b915060208301358015158114612184575f5ffd5b809150509250929050565b5f5f604083850312156121a0575f5ffd5b82356121ab8161206a565b915060208301356121848161206a565b5f5f83601f8401126121cb575f5ffd5b5081356001600160401b038111156121e1575f5ffd5b602083019150836020828501011115610ddf575f5ffd5b5f5f5f6040848603121561220a575f5ffd5b83356122158161206a565b925060208401356001600160401b0381111561222f575f5ffd5b61223b868287016121bb565b9497909650939450505050565b803563ffffffff811681146120d4575f5ffd5b5f5f5f6060848603121561226d575f5ffd5b612276846120be565b925060208401356122868161206a565b915061229460408501612248565b90509250925092565b5f5f604083850312156122ae575f5ffd5b6121ab836120be565b5f5f604083850312156122c8575f5ffd5b6122d1836120be565b91506122df602084016120be565b90509250929050565b5f602082840312156122f8575f5ffd5b5035919050565b5f6020828403121561230f575f5ffd5b81356108f58161206a565b6001600160e01b031981168114612067575f5ffd5b5f5f60408385031215612340575f5ffd5b823561234b8161206a565b915060208301356121848161231a565b5f5f5f6040848603121561236d575f5ffd5b612215846120be565b5f5f60408385031215612387575f5ffd5b612390836120be565b91506122df60208401612248565b5f5f5f5f606085870312156123b1575f5ffd5b84356123bc8161206a565b935060208501356123cc8161206a565b925060408501356001600160401b038111156123e6575f5ffd5b6123f2878288016121bb565b95989497509550505050565b5f5f6020838503121561240f575f5ffd5b82356001600160401b03811115612424575f5ffd5b6124308582860161207e565b90969095509350505050565b5f602082016020835280845180835260408501915060408160051b8601019250602086015f5b828110156124b457603f19878603018452815180518087528060208301602089015e5f602082890101526020601f19601f83011688010196505050602082019150602084019350600181019050612462565b50929695505050505050565b5f5f5f606084860312156124d2575f5ffd5b83356124dd8161206a565b925060208401356124ed8161206a565b915060408401356124fd8161231a565b809150509250925092565b5f5f60408385031215612519575f5ffd5b82356123908161206a565b5f5f5f5f60608587031215612537575f5ffd5b84356125428161206a565b935060208501356001600160401b0381111561255c575f5ffd5b612568878288016121bb565b909450925050604085013565ffffffffffff81168114612586575f5ffd5b939692955090935050565b634e487b7160e01b5f52603260045260245ffd5b5f602082840312156125b5575f5ffd5b81356108f58161231a565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b602081525f6125fb6020830184866125c0565b949350505050565b5f60208284031215612613575f5ffd5b81516108f58161231a565b6001600160a01b038581168252841660208201526060604082018190525f9061147a90830184866125c0565b634e487b7160e01b5f52601160045260245ffd5b5f5f8585111561266c575f5ffd5b83861115612678575f5ffd5b5050820193919092039150565b634e487b7160e01b5f52604160045260245ffd5b5f5f8335601e198436030181126126ae575f5ffd5b8301803591506001600160401b038211156126c7575f5ffd5b602001915036819003821315610ddf575f5ffd5b5f81518060208401855e5f93019283525090919050565b828482375f8382015f815261147a81856126db565b65ffffffffffff81811683821601908111156107525761075261264a565b65ffffffffffff861681526001600160a01b038581166020830152841660408201526080606082018190525f9061275f90830184866125c0565b979650505050505050565b80356001600160e01b0319811690600484101561279b576001600160e01b0319600485900360031b81901b82161691505b5092915050565b5f6108f582846126db565b63ffffffff82811682821603908111156107525761075261264a56fea2646970667358221220038d0185f5b493ced1366a84cfd3c07408ff7eee0e7e5026d0bfbb521ed9408364736f6c634300081b0033", + "deployedBytecode": "0x6080604052600436106101db575f3560e01c80636d5115bd116100fd578063b700961311610092578063d22b598911610062578063d22b598914610636578063d6bb62c614610655578063f801a69814610674578063fe0776f5146106ad575f5ffd5b8063b7009613146105a8578063b7d2b162146105e3578063cc1b6c8114610602578063d1f856ee14610617575f5ffd5b8063a166aa89116100cd578063a166aa8914610501578063a64d95ce14610530578063abd9bd2a1461054f578063ac9650d81461057c575f5ffd5b80636d5115bd1461049157806375b238fc146104b0578063853551b8146104c357806394c7d7ee146104e2575f5ffd5b806330cae187116101735780634665096d116101435780634665096d146104035780634c1da1e2146104185780635296295214610437578063530dd45614610456575f5ffd5b806330cae1871461035c5780633adc277a1461037b5780633ca7c02a146103b15780634136a33c146103cb575f5ffd5b806318ff183c116101ae57806318ff183c146102b25780631cff79cd146102d157806325c471a0146102e45780633078f11414610303575f5ffd5b806308d6122d146101df5780630b0a93ba1461020057806312be87271461025f578063167bd39514610293575b5f5ffd5b3480156101ea575f5ffd5b506101fe6101f93660046120d9565b6106cc565b005b34801561020b575f5ffd5b5061024261021a36600461213b565b6001600160401b039081165f9081526001602081905260409091200154600160401b90041690565b6040516001600160401b0390911681526020015b60405180910390f35b34801561026a575f5ffd5b5061027e61027936600461213b565b61071e565b60405163ffffffff9091168152602001610256565b34801561029e575f5ffd5b506101fe6102ad366004612154565b610758565b3480156102bd575f5ffd5b506101fe6102cc36600461218f565b61076e565b61027e6102df3660046121f8565b6107d0565b3480156102ef575f5ffd5b506101fe6102fe36600461225b565b6108fc565b34801561030e575f5ffd5b5061032261031d36600461229d565b61091e565b604051610256949392919065ffffffffffff948516815263ffffffff93841660208201529190921660408201529116606082015260800190565b348015610367575f5ffd5b506101fe6103763660046122b7565b610982565b348015610386575f5ffd5b5061039a6103953660046122e8565b610994565b60405165ffffffffffff9091168152602001610256565b3480156103bc575f5ffd5b506102426001600160401b0381565b3480156103d6575f5ffd5b5061027e6103e53660046122e8565b5f90815260026020526040902054600160301b900463ffffffff1690565b34801561040e575f5ffd5b5062093a8061027e565b348015610423575f5ffd5b5061027e6104323660046122ff565b6109c5565b348015610442575f5ffd5b506101fe6104513660046122b7565b6109f2565b348015610461575f5ffd5b5061024261047036600461213b565b6001600160401b039081165f90815260016020819052604090912001541690565b34801561049c575f5ffd5b506102426104ab36600461232f565b610a04565b3480156104bb575f5ffd5b506102425f81565b3480156104ce575f5ffd5b506101fe6104dd36600461235b565b610a3e565b3480156104ed575f5ffd5b506101fe6104fc3660046121f8565b610ad5565b34801561050c575f5ffd5b5061052061051b3660046122ff565b610b7f565b6040519015158152602001610256565b34801561053b575f5ffd5b506101fe61054a366004612376565b610ba6565b34801561055a575f5ffd5b5061056e61056936600461239e565b610bb8565b604051908152602001610256565b348015610587575f5ffd5b5061059b6105963660046123fe565b610bf0565b604051610256919061243c565b3480156105b3575f5ffd5b506105c76105c23660046124c0565b610cd5565b60408051921515835263ffffffff909116602083015201610256565b3480156105ee575f5ffd5b506101fe6105fd36600461229d565b610d56565b34801561060d575f5ffd5b506206978061027e565b348015610622575f5ffd5b506105c761063136600461229d565b610d6d565b348015610641575f5ffd5b506101fe610650366004612508565b610de6565b348015610660575f5ffd5b5061027e61066f36600461239e565b610df8565b34801561067f575f5ffd5b5061069361068e366004612524565b610f4b565b6040805192835263ffffffff909116602083015201610256565b3480156106b8575f5ffd5b506101fe6106c736600461229d565b61108c565b6106d46110b5565b5f5b828110156107175761070f858585848181106106f4576106f4612591565b905060200201602081019061070991906125a5565b8461112c565b6001016106d6565b5050505050565b6001600160401b0381165f9081526001602081905260408220015461075290600160801b90046001600160701b03166111ad565b92915050565b6107606110b5565b61076a82826111cb565b5050565b6107766110b5565b604051637a9e5e4b60e01b81526001600160a01b038281166004830152831690637a9e5e4b906024015f604051808303815f87803b1580156107b6575f5ffd5b505af11580156107c8573d5f5f3e3d5ffd5b505050505050565b5f3381806107e08388888861123c565b91509150811580156107f6575063ffffffff8116155b15610849578287610807888861128d565b6040516381c6f24b60e01b81526001600160a01b0393841660048201529290911660248301526001600160e01b03191660448201526064015b60405180910390fd5b5f61085684898989610bb8565b90505f63ffffffff831615158061087c575061087182610994565b65ffffffffffff1615155b1561088d5761088a826112a4565b90505b6003546108a38a61089e8b8b61128d565b6113a2565b6003819055506108ea8a8a8a8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152503492506113e4915050565b506003559450505050505b9392505050565b6109046110b5565b61091883836109128661071e565b84611484565b50505050565b6001600160401b0382165f9081526001602090815260408083206001600160a01b03851684529091528120805465ffffffffffff81169291829182919061097490600160301b90046001600160701b03166116ca565b969991985096509350505050565b61098a6110b5565b61076a82826116eb565b5f8181526002602052604081205465ffffffffffff166109b38161178e565b6109bd57806108f5565b5f9392505050565b6001600160a01b0381165f90815260208190526040812060010154610752906001600160701b03166111ad565b6109fa6110b5565b61076a82826117bc565b6001600160a01b0382165f908152602081815260408083206001600160e01b0319851684529091529020546001600160401b031692915050565b610a466110b5565b6001600160401b0383161580610a6457506001600160401b03838116145b15610a8d5760405163061c6a4360e21b81526001600160401b0384166004820152602401610840565b826001600160401b03167f1256f5b5ecb89caec12db449738f2fbcd1ba5806cf38f35413f4e5c15bf6a4508383604051610ac89291906125e8565b60405180910390a2505050565b60408051638fb3603760e01b80825291513392918391638fb36037916004808201926020929091908290030181865afa158015610b14573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b389190612603565b6001600160e01b03191614610b6b57604051630641fee960e31b81526001600160a01b0382166004820152602401610840565b610717610b7a85838686610bb8565b6112a4565b6001600160a01b03165f90815260208190526040902060010154600160701b900460ff1690565b610bae6110b5565b61076a828261186d565b5f84848484604051602001610bd0949392919061261e565b604051602081830303815290604052805190602001209050949350505050565b604080515f815260208101909152606090826001600160401b03811115610c1957610c19612685565b604051908082528060200260200182016040528015610c4c57816020015b6060815260200190600190039081610c375790505b5091505f5b83811015610ccd57610ca830868684818110610c6f57610c6f612591565b9050602002810190610c819190612699565b85604051602001610c94939291906126f2565b60405160208183030381529060405261197c565b838281518110610cba57610cba612591565b6020908102919091010152600101610c51565b505092915050565b5f5f610ce084610b7f565b15610cef57505f905080610d4e565b306001600160a01b03861603610d1357610d0984846119ee565b5f91509150610d4e565b5f610d1e8585610a04565b90505f5f610d2c8389610d6d565b9150915081610d3c575f5f610d46565b63ffffffff811615815b945094505050505b935093915050565b610d5e6110b5565b610d688282611a04565b505050565b5f8067fffffffffffffffe196001600160401b03851601610d935750600190505f610ddf565b5f5f610d9f868661091e565b5050915091508165ffffffffffff165f14158015610dd45750610dc0611aed565b65ffffffffffff168265ffffffffffff1611155b93509150610ddf9050565b9250929050565b610dee6110b5565b61076a8282611afc565b5f3381610e05858561128d565b90505f610e1488888888610bb8565b5f8181526002602052604081205491925065ffffffffffff9091169003610e515760405163060a299b60e41b815260048101829052602401610840565b826001600160a01b0316886001600160a01b031614610eea575f610e755f85610d6d565b5090505f610e8f610e8961021a8b87610a04565b86610d6d565b50905081158015610e9e575080155b15610ee757604051630ff89d4760e21b81526001600160a01b038087166004830152808c1660248301528a1660448201526001600160e01b031985166064820152608401610840565b50505b5f81815260026020526040808220805465ffffffffffff1916908190559051600160301b90910463ffffffff1691829184917fbd9ac67a6e2f6463b80927326310338bcbb4bdb7936ce1365ea3e01067e7b9f791a398975050505050505050565b5f803381610f5b8289898961123c565b9150505f8163ffffffff16610f6e611aed565b610f789190612707565b905063ffffffff82161580610fae57505f8665ffffffffffff16118015610fae57508065ffffffffffff168665ffffffffffff16105b15610fbf5782896108078a8a61128d565b610fd98665ffffffffffff168265ffffffffffff16611bb7565b9550610fe7838a8a8a610bb8565b9450610ff285611bc6565b5f8581526002602052604090819020805465ffffffffffff891669ffffffffffffffffffff19821617600160301b9182900463ffffffff90811660010190811692830291909117909255915190955086907f82a2da5dee54ea8021c6545b4444620291e07ee83be6dd57edb175062715f3b490611078908a9088908f908f908f90612725565b60405180910390a350505094509492505050565b6001600160a01b0381163314610d5e57604051635f159e6360e01b815260040160405180910390fd5b335f806110c3838236611c12565b9150915081610d68578063ffffffff165f0361111d575f6110e48136611cd5565b5060405163f07e038f60e01b81526001600160a01b03871660048201526001600160401b03821660248201529092506044019050610840565b610918610b7a84305f36610bb8565b6001600160a01b0383165f818152602081815260408083206001600160e01b0319871680855290835292819020805467ffffffffffffffff19166001600160401b038716908117909155905192835292917f9ea6790c7dadfd01c9f8b9762b3682607af2c7e79e05a9f9fdf5580dde949151910160405180910390a3505050565b5f5f6111c1836001600160701b03166116ca565b5090949350505050565b6001600160a01b0382165f81815260208190526040908190206001018054841515600160701b0260ff60701b19909116179055517f90d4e7bb7e5d933792b3562e1741306f8be94837e1348dacef9b6f1df56eb1389061123090841515815260200190565b60405180910390a25050565b5f80306001600160a01b0386160361126257611259868585611c12565b91509150611284565b6004831061127e5761127986866105c2878761128d565b611259565b505f9050805b94509492505050565b5f61129b600482848661265e565b6108f59161276a565b5f8181526002602052604081205465ffffffffffff811690600160301b900463ffffffff168183036112ec5760405163060a299b60e41b815260048101859052602401610840565b6112f4611aed565b65ffffffffffff168265ffffffffffff16111561132757604051630c65b5bd60e11b815260048101859052602401610840565b6113308261178e565b1561135157604051631e2975b960e21b815260048101859052602401610840565b5f84815260026020526040808220805465ffffffffffff191690555163ffffffff83169186917f76a2a46953689d4861a5d3f6ed883ad7e6af674a21f8e162707159fc9dde614d9190a39392505050565b604080516001600160a01b03939093166020808501919091526001600160e01b0319929092168382015280518084038201815260609093019052815191012090565b6060814710156114105760405163cf47918160e01b815247600482015260248101839052604401610840565b5f5f856001600160a01b0316848660405161142b91906127a2565b5f6040518083038185875af1925050503d805f8114611465576040519150601f19603f3d011682016040523d82523d5f602084013e61146a565b606091505b509150915061147a868383611ebb565b9695505050505050565b5f67fffffffffffffffe196001600160401b038616016114c25760405163061c6a4360e21b81526001600160401b0386166004820152602401610840565b6001600160401b0385165f9081526001602090815260408083206001600160a01b038816845290915281205465ffffffffffff16159081156115b2578463ffffffff1661150d611aed565b6115179190612707565b905060405180604001604052808265ffffffffffff1681526020016115458663ffffffff1663ffffffff1690565b6001600160701b039081169091526001600160401b0389165f9081526001602090815260408083206001600160a01b038c1684528252909120835181549490920151909216600160301b026001600160a01b031990931665ffffffffffff9091161791909117905561165c565b6001600160401b0387165f9081526001602090815260408083206001600160a01b038a1684529091528120546115fb91600160301b9091046001600160701b0316908690611f17565b6001600160401b0389165f9081526001602090815260408083206001600160a01b038c168452909152902080546001600160701b03909316600160301b0273ffffffffffffffffffffffffffff000000000000199093169290921790915590505b6040805163ffffffff8616815265ffffffffffff831660208201528315158183015290516001600160a01b038816916001600160401b038a16917ff98448b987f1428e0e230e1f3c6e2ce15b5693eaf31827fbd0b1ec4b424ae7cf9181900360600190a35095945050505050565b5f5f5f6116de846116d9611aed565b611fbd565b9250925092509193909250565b6001600160401b038216158061170957506001600160401b03828116145b156117325760405163061c6a4360e21b81526001600160401b0383166004820152602401610840565b6001600160401b038281165f818152600160208190526040808320909101805467ffffffffffffffff19169486169485179055517f1fd6dd7631312dfac2205b52913f99de03b4d7e381d5d27d3dbfe0713e6e63409190a35050565b5f611797611aed565b65ffffffffffff166117ac62093a8084612707565b65ffffffffffff16111592915050565b6001600160401b03821615806117da57506001600160401b03828116145b156118035760405163061c6a4360e21b81526001600160401b0383166004820152602401610840565b6001600160401b038281165f81815260016020819052604080832090910180546fffffffffffffffff00000000000000001916600160401b958716958602179055517f7a8059630b897b5de4c08ade69f8b90c3ead1f8596d62d10b6c4d14a0afb4ae29190a35050565b67fffffffffffffffe196001600160401b038316016118aa5760405163061c6a4360e21b81526001600160401b0383166004820152602401610840565b6001600160401b0382165f908152600160208190526040822001546118e390600160801b90046001600160701b03168362069780611f17565b6001600160401b0385165f818152600160208190526040918290200180546001600160701b03909516600160801b026dffffffffffffffffffffffffffff60801b199095169490941790935591519092507ffeb69018ee8b8fd50ea86348f1267d07673379f72cffdeccec63853ee8ce8b4890610ac8908590859063ffffffff92909216825265ffffffffffff16602082015260400190565b60605f5f846001600160a01b03168460405161199891906127a2565b5f60405180830381855af49150503d805f81146119d0576040519150601f19603f3d011682016040523d82523d5f602084013e6119d5565b606091505b50915091506119e5858383611ebb565b95945050505050565b5f6119f983836113a2565b600354149392505050565b5f67fffffffffffffffe196001600160401b03841601611a425760405163061c6a4360e21b81526001600160401b0384166004820152602401610840565b6001600160401b0383165f9081526001602090815260408083206001600160a01b038616845290915281205465ffffffffffff169003611a8357505f610752565b6001600160401b0383165f8181526001602090815260408083206001600160a01b038716808552925280832080546001600160a01b0319169055519092917ff229baa593af28c41b1d16b748cd7688f0c83aaf92d4be41c44005defe84c16691a350600192915050565b5f611af742612009565b905090565b6001600160a01b0382165f90815260208190526040812060010154611b2e906001600160701b03168362069780611f17565b6001600160a01b0385165f818152602081815260409182902060010180546dffffffffffffffffffffffffffff19166001600160701b039690961695909517909455805163ffffffff8716815265ffffffffffff841694810194909452919350917fa56b76017453f399ec2327ba00375dbfb1fd070ff854341ad6191e6a2e2de19c9101610ac8565b5f8282188284110282186108f5565b5f8181526002602052604090205465ffffffffffff168015801590611bf15750611bef8161178e565b155b1561076a5760405163813e945960e01b815260048101839052602401610840565b5f806004831015611c2757505f905080610d4e565b306001600160a01b03861603611c4a57610d0930611c45868661128d565b6119ee565b5f5f5f611c578787611cd5565b92509250925082158015611c6f5750611c6f30610b7f565b15611c82575f5f94509450505050610d4e565b5f5f611c8e848b610d6d565b9150915081611ca7575f5f965096505050505050610d4e565b611cbd8363ffffffff168263ffffffff16611bb7565b63ffffffff8116159b909a5098505050505050505050565b5f80806004841015611cee57505f915081905080611eb4565b5f611cf9868661128d565b90506001600160e01b031981166310a6aa3760e31b1480611d2a57506001600160e01b031981166330cae18760e01b145b80611d4557506001600160e01b0319811663294b14a960e11b145b80611d6057506001600160e01b03198116635326cae760e11b145b80611d7b57506001600160e01b0319811663d22b598960e01b145b15611d905760015f5f93509350935050611eb4565b6001600160e01b0319811663063fc60f60e21b1480611dbf57506001600160e01b0319811663167bd39560e01b145b80611dda57506001600160e01b031981166308d6122d60e01b145b15611e19575f611dee60246004888a61265e565b810190611dfb91906122ff565b90505f611e07826109c5565b600196505f95509350611eb492505050565b6001600160e01b0319811663012e238d60e51b1480611e4857506001600160e01b03198116635be958b160e11b145b15611ea0575f611e5c60246004888a61265e565b810190611e69919061213b565b90506001611e92826001600160401b039081165f90815260016020819052604090912001541690565b5f9450945094505050611eb4565b5f611eab3083610a04565b5f935093509350505b9250925092565b606082611ed057611ecb8261203f565b6108f5565b8151158015611ee757506001600160a01b0384163b155b15611f1057604051639996b31560e01b81526001600160a01b0385166004820152602401610840565b50806108f5565b5f5f5f611f2c866001600160701b03166111ad565b90505f611f678563ffffffff168763ffffffff168463ffffffff1611611f52575f611f5c565b611f5c88856127ad565b63ffffffff16611bb7565b90508063ffffffff16611f78611aed565b611f829190612707565b925063ffffffff8616602083901b67ffffffff0000000016604085901b6dffffffffffff000000000000000016171793505050935093915050565b69ffffffffffffffffffff602083901c166001600160701b03831665ffffffffffff604085901c8116908416811115611ff857828282611ffc565b815f5f5b9250925092509250925092565b5f65ffffffffffff82111561203b576040516306dfcc6560e41b81526030600482015260248101839052604401610840565b5090565b80511561204e57805160208201fd5b60405163d6bda27560e01b815260040160405180910390fd5b50565b6001600160a01b0381168114612067575f5ffd5b5f5f83601f84011261208e575f5ffd5b5081356001600160401b038111156120a4575f5ffd5b6020830191508360208260051b8501011115610ddf575f5ffd5b80356001600160401b03811681146120d4575f5ffd5b919050565b5f5f5f5f606085870312156120ec575f5ffd5b84356120f78161206a565b935060208501356001600160401b03811115612111575f5ffd5b61211d8782880161207e565b90945092506121309050604086016120be565b905092959194509250565b5f6020828403121561214b575f5ffd5b6108f5826120be565b5f5f60408385031215612165575f5ffd5b82356121708161206a565b915060208301358015158114612184575f5ffd5b809150509250929050565b5f5f604083850312156121a0575f5ffd5b82356121ab8161206a565b915060208301356121848161206a565b5f5f83601f8401126121cb575f5ffd5b5081356001600160401b038111156121e1575f5ffd5b602083019150836020828501011115610ddf575f5ffd5b5f5f5f6040848603121561220a575f5ffd5b83356122158161206a565b925060208401356001600160401b0381111561222f575f5ffd5b61223b868287016121bb565b9497909650939450505050565b803563ffffffff811681146120d4575f5ffd5b5f5f5f6060848603121561226d575f5ffd5b612276846120be565b925060208401356122868161206a565b915061229460408501612248565b90509250925092565b5f5f604083850312156122ae575f5ffd5b6121ab836120be565b5f5f604083850312156122c8575f5ffd5b6122d1836120be565b91506122df602084016120be565b90509250929050565b5f602082840312156122f8575f5ffd5b5035919050565b5f6020828403121561230f575f5ffd5b81356108f58161206a565b6001600160e01b031981168114612067575f5ffd5b5f5f60408385031215612340575f5ffd5b823561234b8161206a565b915060208301356121848161231a565b5f5f5f6040848603121561236d575f5ffd5b612215846120be565b5f5f60408385031215612387575f5ffd5b612390836120be565b91506122df60208401612248565b5f5f5f5f606085870312156123b1575f5ffd5b84356123bc8161206a565b935060208501356123cc8161206a565b925060408501356001600160401b038111156123e6575f5ffd5b6123f2878288016121bb565b95989497509550505050565b5f5f6020838503121561240f575f5ffd5b82356001600160401b03811115612424575f5ffd5b6124308582860161207e565b90969095509350505050565b5f602082016020835280845180835260408501915060408160051b8601019250602086015f5b828110156124b457603f19878603018452815180518087528060208301602089015e5f602082890101526020601f19601f83011688010196505050602082019150602084019350600181019050612462565b50929695505050505050565b5f5f5f606084860312156124d2575f5ffd5b83356124dd8161206a565b925060208401356124ed8161206a565b915060408401356124fd8161231a565b809150509250925092565b5f5f60408385031215612519575f5ffd5b82356123908161206a565b5f5f5f5f60608587031215612537575f5ffd5b84356125428161206a565b935060208501356001600160401b0381111561255c575f5ffd5b612568878288016121bb565b909450925050604085013565ffffffffffff81168114612586575f5ffd5b939692955090935050565b634e487b7160e01b5f52603260045260245ffd5b5f602082840312156125b5575f5ffd5b81356108f58161231a565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b602081525f6125fb6020830184866125c0565b949350505050565b5f60208284031215612613575f5ffd5b81516108f58161231a565b6001600160a01b038581168252841660208201526060604082018190525f9061147a90830184866125c0565b634e487b7160e01b5f52601160045260245ffd5b5f5f8585111561266c575f5ffd5b83861115612678575f5ffd5b5050820193919092039150565b634e487b7160e01b5f52604160045260245ffd5b5f5f8335601e198436030181126126ae575f5ffd5b8301803591506001600160401b038211156126c7575f5ffd5b602001915036819003821315610ddf575f5ffd5b5f81518060208401855e5f93019283525090919050565b828482375f8382015f815261147a81856126db565b65ffffffffffff81811683821601908111156107525761075261264a565b65ffffffffffff861681526001600160a01b038581166020830152841660408201526080606082018190525f9061275f90830184866125c0565b979650505050505050565b80356001600160e01b0319811690600484101561279b576001600160e01b0319600485900360031b81901b82161691505b5092915050565b5f6108f582846126db565b63ffffffff82811682821603908111156107525761075261264a56fea2646970667358221220038d0185f5b493ced1366a84cfd3c07408ff7eee0e7e5026d0bfbb521ed9408364736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Account.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Account.json new file mode 100644 index 00000000..dcf46f27 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Account.json @@ -0,0 +1,147 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "Account", + "sourceName": "contracts/account/Account.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "AccountUnauthorized", + "type": "error" + }, + { + "inputs": [], + "name": "entryPoint", + "outputs": [ + { + "internalType": "contract IEntryPoint", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint192", + "name": "key", + "type": "uint192" + } + ], + "name": "getNonce", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getNonce", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "initCode", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "callData", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "accountGasLimits", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "preVerificationGas", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "gasFees", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "paymasterAndData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "internalType": "struct PackedUserOperation", + "name": "userOp", + "type": "tuple" + }, + { + "internalType": "bytes32", + "name": "userOpHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "missingAccountFunds", + "type": "uint256" + } + ], + "name": "validateUserOp", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/AccountERC7579.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/AccountERC7579.json new file mode 100644 index 00000000..2a3609ec --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/AccountERC7579.json @@ -0,0 +1,507 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "AccountERC7579", + "sourceName": "contracts/account/extensions/draft-AccountERC7579.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "AccountUnauthorized", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "moduleTypeId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "module", + "type": "address" + } + ], + "name": "ERC7579AlreadyInstalledModule", + "type": "error" + }, + { + "inputs": [], + "name": "ERC7579DecodingError", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "moduleTypeId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "module", + "type": "address" + } + ], + "name": "ERC7579MismatchedModuleTypeId", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "selector", + "type": "bytes4" + } + ], + "name": "ERC7579MissingFallbackHandler", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "moduleTypeId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "module", + "type": "address" + } + ], + "name": "ERC7579UninstalledModule", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "CallType", + "name": "callType", + "type": "bytes1" + } + ], + "name": "ERC7579UnsupportedCallType", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "ExecType", + "name": "execType", + "type": "bytes1" + } + ], + "name": "ERC7579UnsupportedExecType", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "moduleTypeId", + "type": "uint256" + } + ], + "name": "ERC7579UnsupportedModuleType", + "type": "error" + }, + { + "inputs": [], + "name": "FailedCall", + "type": "error" + }, + { + "inputs": [], + "name": "OutOfRangeAccess", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "batchExecutionIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "returndata", + "type": "bytes" + } + ], + "name": "ERC7579TryExecuteFail", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "moduleTypeId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "module", + "type": "address" + } + ], + "name": "ModuleInstalled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "moduleTypeId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "module", + "type": "address" + } + ], + "name": "ModuleUninstalled", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "accountId", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "entryPoint", + "outputs": [ + { + "internalType": "contract IEntryPoint", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "mode", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "executionCalldata", + "type": "bytes" + } + ], + "name": "execute", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "mode", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "executionCalldata", + "type": "bytes" + } + ], + "name": "executeFromExecutor", + "outputs": [ + { + "internalType": "bytes[]", + "name": "returnData", + "type": "bytes[]" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint192", + "name": "key", + "type": "uint192" + } + ], + "name": "getNonce", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getNonce", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "moduleTypeId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "module", + "type": "address" + }, + { + "internalType": "bytes", + "name": "initData", + "type": "bytes" + } + ], + "name": "installModule", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "moduleTypeId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "module", + "type": "address" + }, + { + "internalType": "bytes", + "name": "additionalContext", + "type": "bytes" + } + ], + "name": "isModuleInstalled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "isValidSignature", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "encodedMode", + "type": "bytes32" + } + ], + "name": "supportsExecutionMode", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "moduleTypeId", + "type": "uint256" + } + ], + "name": "supportsModule", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "moduleTypeId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "module", + "type": "address" + }, + { + "internalType": "bytes", + "name": "deInitData", + "type": "bytes" + } + ], + "name": "uninstallModule", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "initCode", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "callData", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "accountGasLimits", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "preVerificationGas", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "gasFees", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "paymasterAndData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "internalType": "struct PackedUserOperation", + "name": "userOp", + "type": "tuple" + }, + { + "internalType": "bytes32", + "name": "userOpHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "missingAccountFunds", + "type": "uint256" + } + ], + "name": "validateUserOp", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/AccountERC7579Hooked.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/AccountERC7579Hooked.json new file mode 100644 index 00000000..091c958c --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/AccountERC7579Hooked.json @@ -0,0 +1,531 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "AccountERC7579Hooked", + "sourceName": "contracts/account/extensions/draft-AccountERC7579Hooked.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "AccountUnauthorized", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "moduleTypeId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "module", + "type": "address" + } + ], + "name": "ERC7579AlreadyInstalledModule", + "type": "error" + }, + { + "inputs": [], + "name": "ERC7579DecodingError", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "hook", + "type": "address" + } + ], + "name": "ERC7579HookModuleAlreadyPresent", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "moduleTypeId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "module", + "type": "address" + } + ], + "name": "ERC7579MismatchedModuleTypeId", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "selector", + "type": "bytes4" + } + ], + "name": "ERC7579MissingFallbackHandler", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "moduleTypeId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "module", + "type": "address" + } + ], + "name": "ERC7579UninstalledModule", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "CallType", + "name": "callType", + "type": "bytes1" + } + ], + "name": "ERC7579UnsupportedCallType", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "ExecType", + "name": "execType", + "type": "bytes1" + } + ], + "name": "ERC7579UnsupportedExecType", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "moduleTypeId", + "type": "uint256" + } + ], + "name": "ERC7579UnsupportedModuleType", + "type": "error" + }, + { + "inputs": [], + "name": "FailedCall", + "type": "error" + }, + { + "inputs": [], + "name": "OutOfRangeAccess", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "batchExecutionIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "returndata", + "type": "bytes" + } + ], + "name": "ERC7579TryExecuteFail", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "moduleTypeId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "module", + "type": "address" + } + ], + "name": "ModuleInstalled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "moduleTypeId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "module", + "type": "address" + } + ], + "name": "ModuleUninstalled", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "accountId", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "entryPoint", + "outputs": [ + { + "internalType": "contract IEntryPoint", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "mode", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "executionCalldata", + "type": "bytes" + } + ], + "name": "execute", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "mode", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "executionCalldata", + "type": "bytes" + } + ], + "name": "executeFromExecutor", + "outputs": [ + { + "internalType": "bytes[]", + "name": "returnData", + "type": "bytes[]" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint192", + "name": "key", + "type": "uint192" + } + ], + "name": "getNonce", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getNonce", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "hook", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "moduleTypeId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "module", + "type": "address" + }, + { + "internalType": "bytes", + "name": "initData", + "type": "bytes" + } + ], + "name": "installModule", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "moduleTypeId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "module", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "isModuleInstalled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "isValidSignature", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "encodedMode", + "type": "bytes32" + } + ], + "name": "supportsExecutionMode", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "moduleTypeId", + "type": "uint256" + } + ], + "name": "supportsModule", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "moduleTypeId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "module", + "type": "address" + }, + { + "internalType": "bytes", + "name": "deInitData", + "type": "bytes" + } + ], + "name": "uninstallModule", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "initCode", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "callData", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "accountGasLimits", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "preVerificationGas", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "gasFees", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "paymasterAndData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "internalType": "struct PackedUserOperation", + "name": "userOp", + "type": "tuple" + }, + { + "internalType": "bytes32", + "name": "userOpHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "missingAccountFunds", + "type": "uint256" + } + ], + "name": "validateUserOp", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Address.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Address.json new file mode 100644 index 00000000..e67878e4 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Address.json @@ -0,0 +1,22 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "Address", + "sourceName": "contracts/utils/Address.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "AddressEmptyCode", + "type": "error" + } + ], + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220515c377018d6c14d36f6a76b411796fc698e379f1e95e2d9475d6ac3aa946d5764736f6c634300081b0033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220515c377018d6c14d36f6a76b411796fc698e379f1e95e2d9475d6ac3aa946d5764736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Arrays.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Arrays.json new file mode 100644 index 00000000..443c7e75 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Arrays.json @@ -0,0 +1,10 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "Arrays", + "sourceName": "contracts/utils/Arrays.sol", + "abi": [], + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220373a7300d02c9adbb63b2237a18303d4291c9738e2ad8bd2357080e9274131d164736f6c634300081b0033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220373a7300d02c9adbb63b2237a18303d4291c9738e2ad8bd2357080e9274131d164736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/AuthorityUtils.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/AuthorityUtils.json new file mode 100644 index 00000000..e5f70864 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/AuthorityUtils.json @@ -0,0 +1,10 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "AuthorityUtils", + "sourceName": "contracts/access/manager/AuthorityUtils.sol", + "abi": [], + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220b9cd713c51ade5ddc2edcb79fa4d9cb7a8947ce92d2c688ea89c6cd0c578871f64736f6c634300081b0033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220b9cd713c51ade5ddc2edcb79fa4d9cb7a8947ce92d2c688ea89c6cd0c578871f64736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Base64.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Base64.json new file mode 100644 index 00000000..0aa4e66e --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Base64.json @@ -0,0 +1,10 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "Base64", + "sourceName": "contracts/utils/Base64.sol", + "abi": [], + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220acdc75ba573c9144f54e1c43ec33668b4f8066b84528caa0507568726fd3c1b864736f6c634300081b0033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220acdc75ba573c9144f54e1c43ec33668b4f8066b84528caa0507568726fd3c1b864736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/BeaconProxy.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/BeaconProxy.json new file mode 100644 index 00000000..cad8de7d --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/BeaconProxy.json @@ -0,0 +1,87 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "BeaconProxy", + "sourceName": "contracts/proxy/beacon/BeaconProxy.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "beacon", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "AddressEmptyCode", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "ERC1967InvalidBeacon", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "ERC1967InvalidImplementation", + "type": "error" + }, + { + "inputs": [], + "name": "ERC1967NonPayable", + "type": "error" + }, + { + "inputs": [], + "name": "FailedCall", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + } + ], + "bytecode": "0x60a060405260405161057638038061057683398101604081905261002291610353565b61002c828261003e565b506001600160a01b0316608052610444565b610047826100fb565b6040516001600160a01b038316907f1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e905f90a28051156100ef576100ea826001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100c0573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906100e49190610415565b82610209565b505050565b6100f761027c565b5050565b806001600160a01b03163b5f0361013557604051631933b43b60e21b81526001600160a01b03821660048201526024015b60405180910390fd5b807fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d5080546001600160a01b0319166001600160a01b0392831617905560408051635c60da1b60e01b815290515f92841691635c60da1b9160048083019260209291908290030181865afa1580156101ae573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906101d29190610415565b9050806001600160a01b03163b5f036100f757604051634c9c8ce360e01b81526001600160a01b038216600482015260240161012c565b60605f5f846001600160a01b031684604051610225919061042e565b5f60405180830381855af49150503d805f811461025d576040519150601f19603f3d011682016040523d82523d5f602084013e610262565b606091505b50909250905061027385838361029d565b95945050505050565b341561029b5760405163b398979f60e01b815260040160405180910390fd5b565b6060826102b2576102ad826102fc565b6102f5565b81511580156102c957506001600160a01b0384163b155b156102f257604051639996b31560e01b81526001600160a01b038516600482015260240161012c565b50805b9392505050565b80511561030b57805160208201fd5b60405163d6bda27560e01b815260040160405180910390fd5b80516001600160a01b038116811461033a575f5ffd5b919050565b634e487b7160e01b5f52604160045260245ffd5b5f5f60408385031215610364575f5ffd5b61036d83610324565b60208401519092506001600160401b03811115610388575f5ffd5b8301601f81018513610398575f5ffd5b80516001600160401b038111156103b1576103b161033f565b604051601f8201601f19908116603f011681016001600160401b03811182821017156103df576103df61033f565b6040528181528282016020018710156103f6575f5ffd5b8160208401602083015e5f602083830101528093505050509250929050565b5f60208284031215610425575f5ffd5b6102f582610324565b5f82518060208501845e5f920191825250919050565b60805161011b61045b5f395f601d015261011b5ff3fe6080604052600a600c565b005b60186014601a565b609d565b565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156076573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906098919060ba565b905090565b365f5f375f5f365f845af43d5f5f3e80801560b6573d5ff35b3d5ffd5b5f6020828403121560c9575f5ffd5b81516001600160a01b038116811460de575f5ffd5b939250505056fea26469706673582212205a4974688ab5a2dacc0cd413ae692cf37c2eec059fb1da5d86424a6d627fac0a64736f6c634300081b0033", + "deployedBytecode": "0x6080604052600a600c565b005b60186014601a565b609d565b565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156076573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906098919060ba565b905090565b365f5f375f5f365f845af43d5f5f3e80801560b6573d5ff35b3d5ffd5b5f6020828403121560c9575f5ffd5b81516001600160a01b038116811460de575f5ffd5b939250505056fea26469706673582212205a4974688ab5a2dacc0cd413ae692cf37c2eec059fb1da5d86424a6d627fac0a64736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/BitMaps.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/BitMaps.json new file mode 100644 index 00000000..48b9b640 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/BitMaps.json @@ -0,0 +1,10 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "BitMaps", + "sourceName": "contracts/utils/structs/BitMaps.sol", + "abi": [], + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220f8968052b6c914ec8df760e7c1806604ab7a793d17884410a6635309dcfcfe2f64736f6c634300081b0033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220f8968052b6c914ec8df760e7c1806604ab7a793d17884410a6635309dcfcfe2f64736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Blockhash.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Blockhash.json new file mode 100644 index 00000000..c71c1056 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Blockhash.json @@ -0,0 +1,10 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "Blockhash", + "sourceName": "contracts/utils/Blockhash.sol", + "abi": [], + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122052d8b50a861b5e17bacb1948eca23bc6303361a5115a87535132167384d10e9664736f6c634300081b0033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122052d8b50a861b5e17bacb1948eca23bc6303361a5115a87535132167384d10e9664736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Bytes.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Bytes.json new file mode 100644 index 00000000..bfff3f92 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Bytes.json @@ -0,0 +1,10 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "Bytes", + "sourceName": "contracts/utils/Bytes.sol", + "abi": [], + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122043450f5bcef09ff7984f593a734736c08e1c70e84d99f8eefa43befaf58321f264736f6c634300081b0033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122043450f5bcef09ff7984f593a734736c08e1c70e84d99f8eefa43befaf58321f264736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/CAIP10.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/CAIP10.json new file mode 100644 index 00000000..0a037eff --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/CAIP10.json @@ -0,0 +1,10 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "CAIP10", + "sourceName": "contracts/utils/CAIP10.sol", + "abi": [], + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122070db06ee09344651e592019d903baad77901495d2e8c46a8e6e74f213fbe997c64736f6c634300081b0033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122070db06ee09344651e592019d903baad77901495d2e8c46a8e6e74f213fbe997c64736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/CAIP2.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/CAIP2.json new file mode 100644 index 00000000..b8d918f6 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/CAIP2.json @@ -0,0 +1,10 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "CAIP2", + "sourceName": "contracts/utils/CAIP2.sol", + "abi": [], + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212206f48be56822e7c83f60293319b1ebbb61a03c0d72610488122f29bc45d5adbcd64736f6c634300081b0033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212206f48be56822e7c83f60293319b1ebbb61a03c0d72610488122f29bc45d5adbcd64736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Calldata.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Calldata.json new file mode 100644 index 00000000..d1b4bcb4 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Calldata.json @@ -0,0 +1,10 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "Calldata", + "sourceName": "contracts/utils/Calldata.sol", + "abi": [], + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220506f6e918ef26ff04a4fe97cde177d339251c154181b745c2c11e6c64788831c64736f6c634300081b0033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220506f6e918ef26ff04a4fe97cde177d339251c154181b745c2c11e6c64788831c64736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Checkpoints.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Checkpoints.json new file mode 100644 index 00000000..c1e052e4 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Checkpoints.json @@ -0,0 +1,16 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "Checkpoints", + "sourceName": "contracts/utils/structs/Checkpoints.sol", + "abi": [ + { + "inputs": [], + "name": "CheckpointUnorderedInsertion", + "type": "error" + } + ], + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220149aacbddaad3bd72aecb3b6d006fb05213c471bd9aa8edc0152349c82a9591a64736f6c634300081b0033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220149aacbddaad3bd72aecb3b6d006fb05213c471bd9aa8edc0152349c82a9591a64736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/CircularBuffer.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/CircularBuffer.json new file mode 100644 index 00000000..b932df37 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/CircularBuffer.json @@ -0,0 +1,16 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "CircularBuffer", + "sourceName": "contracts/utils/structs/CircularBuffer.sol", + "abi": [ + { + "inputs": [], + "name": "InvalidBufferSize", + "type": "error" + } + ], + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220b524081b61b43d32570362790a283b52331c1a8f9e6868dff89fa8934368225d64736f6c634300081b0033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220b524081b61b43d32570362790a283b52331c1a8f9e6868dff89fa8934368225d64736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Clones.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Clones.json new file mode 100644 index 00000000..bb6bce94 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Clones.json @@ -0,0 +1,16 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "Clones", + "sourceName": "contracts/proxy/Clones.sol", + "abi": [ + { + "inputs": [], + "name": "CloneArgumentsTooLong", + "type": "error" + } + ], + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212203c07574ef3603a3d83ea97e480faf397c2560f448ac01f5a8d5ea83f09db477d64736f6c634300081b0033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212203c07574ef3603a3d83ea97e480faf397c2560f448ac01f5a8d5ea83f09db477d64736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Comparators.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Comparators.json new file mode 100644 index 00000000..f490d3cd --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Comparators.json @@ -0,0 +1,10 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "Comparators", + "sourceName": "contracts/utils/Comparators.sol", + "abi": [], + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220ada21df4adb0d4c2668e55a8c600d50cf0965c7272ac0c34d8f031672b648a1864736f6c634300081b0033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220ada21df4adb0d4c2668e55a8c600d50cf0965c7272ac0c34d8f031672b648a1864736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Context.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Context.json new file mode 100644 index 00000000..184c2e19 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Context.json @@ -0,0 +1,10 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "Context", + "sourceName": "contracts/utils/Context.sol", + "abi": [], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Create2.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Create2.json new file mode 100644 index 00000000..7b21b0d4 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Create2.json @@ -0,0 +1,16 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "Create2", + "sourceName": "contracts/utils/Create2.sol", + "abi": [ + { + "inputs": [], + "name": "Create2EmptyBytecode", + "type": "error" + } + ], + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220f83e5872af4a9af66481f05111d8261ed5e7c90ef642adffcb1b82f4a3bb376364736f6c634300081b0033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220f83e5872af4a9af66481f05111d8261ed5e7c90ef642adffcb1b82f4a3bb376364736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/DoubleEndedQueue.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/DoubleEndedQueue.json new file mode 100644 index 00000000..a021e914 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/DoubleEndedQueue.json @@ -0,0 +1,10 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "DoubleEndedQueue", + "sourceName": "contracts/utils/structs/DoubleEndedQueue.sol", + "abi": [], + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220fec2a619b619939a4c620cfa859a72e7778a25891b435c1dbf62ef97f0e599d664736f6c634300081b0033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220fec2a619b619939a4c620cfa859a72e7778a25891b435c1dbf62ef97f0e599d664736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ECDSA.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ECDSA.json new file mode 100644 index 00000000..5850c8c9 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ECDSA.json @@ -0,0 +1,38 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ECDSA", + "sourceName": "contracts/utils/cryptography/ECDSA.sol", + "abi": [ + { + "inputs": [], + "name": "ECDSAInvalidSignature", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "length", + "type": "uint256" + } + ], + "name": "ECDSAInvalidSignatureLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "ECDSAInvalidSignatureS", + "type": "error" + } + ], + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220b1584417426ec446135f2ff24669811e405d8a4ad40aa1e08a105a5ee770690e64736f6c634300081b0033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220b1584417426ec446135f2ff24669811e405d8a4ad40aa1e08a105a5ee770690e64736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/EIP712.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/EIP712.json new file mode 100644 index 00000000..df0d3d6e --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/EIP712.json @@ -0,0 +1,76 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "EIP712", + "sourceName": "contracts/utils/cryptography/EIP712.sol", + "abi": [ + { + "inputs": [], + "name": "InvalidShortString", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "str", + "type": "string" + } + ], + "name": "StringTooLong", + "type": "error" + }, + { + "anonymous": false, + "inputs": [], + "name": "EIP712DomainChanged", + "type": "event" + }, + { + "inputs": [], + "name": "eip712Domain", + "outputs": [ + { + "internalType": "bytes1", + "name": "fields", + "type": "bytes1" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "version", + "type": "string" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "verifyingContract", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + }, + { + "internalType": "uint256[]", + "name": "extensions", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/EIP7702Utils.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/EIP7702Utils.json new file mode 100644 index 00000000..76cd9457 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/EIP7702Utils.json @@ -0,0 +1,10 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "EIP7702Utils", + "sourceName": "contracts/account/utils/EIP7702Utils.sol", + "abi": [], + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220d367cc4ace5149f519927ce1e484a6322e09a76aa9d393b13c6c5d2f3a2e3ff864736f6c634300081b0033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220d367cc4ace5149f519927ce1e484a6322e09a76aa9d393b13c6c5d2f3a2e3ff864736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC1155.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC1155.json new file mode 100644 index 00000000..c98707aa --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC1155.json @@ -0,0 +1,425 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ERC1155", + "sourceName": "contracts/token/ERC1155/ERC1155.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ERC1155InsufficientBalance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "approver", + "type": "address" + } + ], + "name": "ERC1155InvalidApprover", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "idsLength", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "valuesLength", + "type": "uint256" + } + ], + "name": "ERC1155InvalidArrayLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "ERC1155InvalidOperator", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ERC1155InvalidReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ERC1155InvalidSender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "ERC1155MissingApprovalForAll", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "ApprovalForAll", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + } + ], + "name": "TransferBatch", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "TransferSingle", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "value", + "type": "string" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "URI", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "accounts", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + } + ], + "name": "balanceOfBatch", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "isApprovedForAll", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeBatchTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setApprovalForAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "uri", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC1155Burnable.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC1155Burnable.json new file mode 100644 index 00000000..0a424d80 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC1155Burnable.json @@ -0,0 +1,471 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ERC1155Burnable", + "sourceName": "contracts/token/ERC1155/extensions/ERC1155Burnable.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ERC1155InsufficientBalance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "approver", + "type": "address" + } + ], + "name": "ERC1155InvalidApprover", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "idsLength", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "valuesLength", + "type": "uint256" + } + ], + "name": "ERC1155InvalidArrayLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "ERC1155InvalidOperator", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ERC1155InvalidReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ERC1155InvalidSender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "ERC1155MissingApprovalForAll", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "ApprovalForAll", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + } + ], + "name": "TransferBatch", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "TransferSingle", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "value", + "type": "string" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "URI", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "accounts", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + } + ], + "name": "balanceOfBatch", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + } + ], + "name": "burnBatch", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "isApprovedForAll", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeBatchTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setApprovalForAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "uri", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC1155Holder.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC1155Holder.json new file mode 100644 index 00000000..5e048661 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC1155Holder.json @@ -0,0 +1,108 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ERC1155Holder", + "sourceName": "contracts/token/ERC1155/utils/ERC1155Holder.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC1155BatchReceived", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC1155Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC1155Pausable.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC1155Pausable.json new file mode 100644 index 00000000..fb5df926 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC1155Pausable.json @@ -0,0 +1,474 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ERC1155Pausable", + "sourceName": "contracts/token/ERC1155/extensions/ERC1155Pausable.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ERC1155InsufficientBalance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "approver", + "type": "address" + } + ], + "name": "ERC1155InvalidApprover", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "idsLength", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "valuesLength", + "type": "uint256" + } + ], + "name": "ERC1155InvalidArrayLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "ERC1155InvalidOperator", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ERC1155InvalidReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ERC1155InvalidSender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "ERC1155MissingApprovalForAll", + "type": "error" + }, + { + "inputs": [], + "name": "EnforcedPause", + "type": "error" + }, + { + "inputs": [], + "name": "ExpectedPause", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "ApprovalForAll", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + } + ], + "name": "TransferBatch", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "TransferSingle", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "value", + "type": "string" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "URI", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "accounts", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + } + ], + "name": "balanceOfBatch", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "isApprovedForAll", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeBatchTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setApprovalForAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "uri", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC1155Supply.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC1155Supply.json new file mode 100644 index 00000000..f2fddb16 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC1155Supply.json @@ -0,0 +1,476 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ERC1155Supply", + "sourceName": "contracts/token/ERC1155/extensions/ERC1155Supply.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ERC1155InsufficientBalance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "approver", + "type": "address" + } + ], + "name": "ERC1155InvalidApprover", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "idsLength", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "valuesLength", + "type": "uint256" + } + ], + "name": "ERC1155InvalidArrayLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "ERC1155InvalidOperator", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ERC1155InvalidReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ERC1155InvalidSender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "ERC1155MissingApprovalForAll", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "ApprovalForAll", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + } + ], + "name": "TransferBatch", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "TransferSingle", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "value", + "type": "string" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "URI", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "accounts", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + } + ], + "name": "balanceOfBatch", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "exists", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "isApprovedForAll", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeBatchTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setApprovalForAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "uri", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC1155URIStorage.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC1155URIStorage.json new file mode 100644 index 00000000..a896e401 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC1155URIStorage.json @@ -0,0 +1,425 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ERC1155URIStorage", + "sourceName": "contracts/token/ERC1155/extensions/ERC1155URIStorage.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ERC1155InsufficientBalance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "approver", + "type": "address" + } + ], + "name": "ERC1155InvalidApprover", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "idsLength", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "valuesLength", + "type": "uint256" + } + ], + "name": "ERC1155InvalidArrayLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "ERC1155InvalidOperator", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ERC1155InvalidReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ERC1155InvalidSender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "ERC1155MissingApprovalForAll", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "ApprovalForAll", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + } + ], + "name": "TransferBatch", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "TransferSingle", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "value", + "type": "string" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "URI", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "accounts", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + } + ], + "name": "balanceOfBatch", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "isApprovedForAll", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeBatchTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setApprovalForAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "uri", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC1155Utils.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC1155Utils.json new file mode 100644 index 00000000..32d3e9c8 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC1155Utils.json @@ -0,0 +1,10 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ERC1155Utils", + "sourceName": "contracts/token/ERC1155/utils/ERC1155Utils.sol", + "abi": [], + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212202111b9982c8ecc5b2aae86c047c7950f99c905e3e7cb42d3f145e5ee6d52248164736f6c634300081b0033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212202111b9982c8ecc5b2aae86c047c7950f99c905e3e7cb42d3f145e5ee6d52248164736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC1363.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC1363.json new file mode 100644 index 00000000..618163ff --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC1363.json @@ -0,0 +1,582 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ERC1363", + "sourceName": "contracts/token/ERC20/extensions/ERC1363.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "ERC1363ApproveFailed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ERC1363InvalidReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "ERC1363InvalidSpender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "ERC1363TransferFailed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "ERC1363TransferFromFailed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "allowance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + } + ], + "name": "ERC20InsufficientAllowance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + } + ], + "name": "ERC20InsufficientBalance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "approver", + "type": "address" + } + ], + "name": "ERC20InvalidApprover", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ERC20InvalidReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ERC20InvalidSender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "ERC20InvalidSpender", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "approveAndCall", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "approveAndCall", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferAndCall", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "transferAndCall", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "transferFromAndCall", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferFromAndCall", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC1363Utils.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC1363Utils.json new file mode 100644 index 00000000..e8b220d1 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC1363Utils.json @@ -0,0 +1,33 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ERC1363Utils", + "sourceName": "contracts/token/ERC20/utils/ERC1363Utils.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ERC1363InvalidReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "ERC1363InvalidSpender", + "type": "error" + } + ], + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122000d3f31db57c613822f20faac816d201f94a662e82977cf0e5e133b4f2fcf9a364736f6c634300081b0033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122000d3f31db57c613822f20faac816d201f94a662e82977cf0e5e133b4f2fcf9a364736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC165.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC165.json new file mode 100644 index 00000000..e1bfd6b4 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC165.json @@ -0,0 +1,30 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ERC165", + "sourceName": "contracts/utils/introspection/ERC165.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC165Checker.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC165Checker.json new file mode 100644 index 00000000..2f6ecbbd --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC165Checker.json @@ -0,0 +1,10 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ERC165Checker", + "sourceName": "contracts/utils/introspection/ERC165Checker.sol", + "abi": [], + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212206da5d1b222bf6d1c2ba7261b71060308b7a5d5f9bbb643b1eb615c649416323c64736f6c634300081b0033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212206da5d1b222bf6d1c2ba7261b71060308b7a5d5f9bbb643b1eb615c649416323c64736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC1967Proxy.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC1967Proxy.json new file mode 100644 index 00000000..395b80a4 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC1967Proxy.json @@ -0,0 +1,76 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ERC1967Proxy", + "sourceName": "contracts/proxy/ERC1967/ERC1967Proxy.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "implementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "AddressEmptyCode", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "ERC1967InvalidImplementation", + "type": "error" + }, + { + "inputs": [], + "name": "ERC1967NonPayable", + "type": "error" + }, + { + "inputs": [], + "name": "FailedCall", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + } + ], + "bytecode": "0x60806040526040516103cf3803806103cf8339810160408190526100229161023b565b61002c8282610033565b5050610320565b61003c82610091565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a280511561008557610080828261010c565b505050565b61008d61017f565b5050565b806001600160a01b03163b5f036100cb57604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0392909216919091179055565b60605f5f846001600160a01b031684604051610128919061030a565b5f60405180830381855af49150503d805f8114610160576040519150601f19603f3d011682016040523d82523d5f602084013e610165565b606091505b5090925090506101768583836101a0565b95945050505050565b341561019e5760405163b398979f60e01b815260040160405180910390fd5b565b6060826101b5576101b0826101ff565b6101f8565b81511580156101cc57506001600160a01b0384163b155b156101f557604051639996b31560e01b81526001600160a01b03851660048201526024016100c2565b50805b9392505050565b80511561020e57805160208201fd5b60405163d6bda27560e01b815260040160405180910390fd5b634e487b7160e01b5f52604160045260245ffd5b5f5f6040838503121561024c575f5ffd5b82516001600160a01b0381168114610262575f5ffd5b60208401519092506001600160401b0381111561027d575f5ffd5b8301601f8101851361028d575f5ffd5b80516001600160401b038111156102a6576102a6610227565b604051601f8201601f19908116603f011681016001600160401b03811182821017156102d4576102d4610227565b6040528181528282016020018710156102eb575f5ffd5b8160208401602083015e5f602083830101528093505050509250929050565b5f82518060208501845e5f920191825250919050565b60a38061032c5f395ff3fe6080604052600a600c565b005b60186014601a565b6050565b565b5f604b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b905090565b365f5f375f5f365f845af43d5f5f3e8080156069573d5ff35b3d5ffdfea264697066735822122023d00a10d61ae41686f714f0e97344848b3227e238c22c1e24cd7f858228f98864736f6c634300081b0033", + "deployedBytecode": "0x6080604052600a600c565b005b60186014601a565b6050565b565b5f604b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b905090565b365f5f375f5f365f845af43d5f5f3e8080156069573d5ff35b3d5ffdfea264697066735822122023d00a10d61ae41686f714f0e97344848b3227e238c22c1e24cd7f858228f98864736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC1967Utils.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC1967Utils.json new file mode 100644 index 00000000..7487cbd6 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC1967Utils.json @@ -0,0 +1,49 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ERC1967Utils", + "sourceName": "contracts/proxy/ERC1967/ERC1967Utils.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "ERC1967InvalidAdmin", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "ERC1967InvalidBeacon", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "ERC1967InvalidImplementation", + "type": "error" + }, + { + "inputs": [], + "name": "ERC1967NonPayable", + "type": "error" + } + ], + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220632ade5569700b1b6c0d5a63cf8d1120358a3b85cac6f2938ae615b83b0b999c64736f6c634300081b0033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220632ade5569700b1b6c0d5a63cf8d1120358a3b85cac6f2938ae615b83b0b999c64736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC20.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC20.json new file mode 100644 index 00000000..b74b1b22 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC20.json @@ -0,0 +1,319 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ERC20", + "sourceName": "contracts/token/ERC20/ERC20.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "allowance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + } + ], + "name": "ERC20InsufficientAllowance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + } + ], + "name": "ERC20InsufficientBalance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "approver", + "type": "address" + } + ], + "name": "ERC20InvalidApprover", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ERC20InvalidReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ERC20InvalidSender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "ERC20InvalidSpender", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC20Bridgeable.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC20Bridgeable.json new file mode 100644 index 00000000..8874c2d4 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC20Bridgeable.json @@ -0,0 +1,424 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ERC20Bridgeable", + "sourceName": "contracts/token/ERC20/extensions/draft-ERC20Bridgeable.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "allowance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + } + ], + "name": "ERC20InsufficientAllowance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + } + ], + "name": "ERC20InsufficientBalance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "approver", + "type": "address" + } + ], + "name": "ERC20InvalidApprover", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ERC20InvalidReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ERC20InvalidSender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "ERC20InvalidSpender", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "CrosschainBurn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "CrosschainMint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "crosschainBurn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "crosschainMint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC20Burnable.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC20Burnable.json new file mode 100644 index 00000000..bb150265 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC20Burnable.json @@ -0,0 +1,350 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ERC20Burnable", + "sourceName": "contracts/token/ERC20/extensions/ERC20Burnable.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "allowance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + } + ], + "name": "ERC20InsufficientAllowance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + } + ], + "name": "ERC20InsufficientBalance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "approver", + "type": "address" + } + ], + "name": "ERC20InvalidApprover", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ERC20InvalidReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ERC20InvalidSender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "ERC20InvalidSpender", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "burnFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC20Capped.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC20Capped.json new file mode 100644 index 00000000..b93041e5 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC20Capped.json @@ -0,0 +1,359 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ERC20Capped", + "sourceName": "contracts/token/ERC20/extensions/ERC20Capped.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "uint256", + "name": "increasedSupply", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "cap", + "type": "uint256" + } + ], + "name": "ERC20ExceededCap", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "allowance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + } + ], + "name": "ERC20InsufficientAllowance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + } + ], + "name": "ERC20InsufficientBalance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "approver", + "type": "address" + } + ], + "name": "ERC20InvalidApprover", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "cap", + "type": "uint256" + } + ], + "name": "ERC20InvalidCap", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ERC20InvalidReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ERC20InvalidSender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "ERC20InvalidSpender", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "cap", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC20FlashMint.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC20FlashMint.json new file mode 100644 index 00000000..16a416ca --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC20FlashMint.json @@ -0,0 +1,429 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ERC20FlashMint", + "sourceName": "contracts/token/ERC20/extensions/ERC20FlashMint.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "allowance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + } + ], + "name": "ERC20InsufficientAllowance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + } + ], + "name": "ERC20InsufficientBalance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "approver", + "type": "address" + } + ], + "name": "ERC20InvalidApprover", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ERC20InvalidReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ERC20InvalidSender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "ERC20InvalidSpender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "maxLoan", + "type": "uint256" + } + ], + "name": "ERC3156ExceededMaxLoan", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ERC3156InvalidReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "ERC3156UnsupportedToken", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "flashFee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC3156FlashBorrower", + "name": "receiver", + "type": "address" + }, + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "flashLoan", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "maxFlashLoan", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC20Pausable.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC20Pausable.json new file mode 100644 index 00000000..bf70a4b6 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC20Pausable.json @@ -0,0 +1,368 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ERC20Pausable", + "sourceName": "contracts/token/ERC20/extensions/ERC20Pausable.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "allowance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + } + ], + "name": "ERC20InsufficientAllowance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + } + ], + "name": "ERC20InsufficientBalance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "approver", + "type": "address" + } + ], + "name": "ERC20InvalidApprover", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ERC20InvalidReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ERC20InvalidSender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "ERC20InvalidSpender", + "type": "error" + }, + { + "inputs": [], + "name": "EnforcedPause", + "type": "error" + }, + { + "inputs": [], + "name": "ExpectedPause", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC20Permit.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC20Permit.json new file mode 100644 index 00000000..48da540b --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC20Permit.json @@ -0,0 +1,529 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ERC20Permit", + "sourceName": "contracts/token/ERC20/extensions/ERC20Permit.sol", + "abi": [ + { + "inputs": [], + "name": "ECDSAInvalidSignature", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "length", + "type": "uint256" + } + ], + "name": "ECDSAInvalidSignatureLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "ECDSAInvalidSignatureS", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "allowance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + } + ], + "name": "ERC20InsufficientAllowance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + } + ], + "name": "ERC20InsufficientBalance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "approver", + "type": "address" + } + ], + "name": "ERC20InvalidApprover", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ERC20InvalidReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ERC20InvalidSender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "ERC20InvalidSpender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "ERC2612ExpiredSignature", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "signer", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "ERC2612InvalidSigner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "currentNonce", + "type": "uint256" + } + ], + "name": "InvalidAccountNonce", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidShortString", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "str", + "type": "string" + } + ], + "name": "StringTooLong", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "EIP712DomainChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [], + "name": "DOMAIN_SEPARATOR", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "eip712Domain", + "outputs": [ + { + "internalType": "bytes1", + "name": "fields", + "type": "bytes1" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "version", + "type": "string" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "verifyingContract", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + }, + { + "internalType": "uint256[]", + "name": "extensions", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "permit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC20TemporaryApproval.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC20TemporaryApproval.json new file mode 100644 index 00000000..779387b9 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC20TemporaryApproval.json @@ -0,0 +1,343 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ERC20TemporaryApproval", + "sourceName": "contracts/token/ERC20/extensions/draft-ERC20TemporaryApproval.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "allowance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + } + ], + "name": "ERC20InsufficientAllowance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + } + ], + "name": "ERC20InsufficientBalance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "approver", + "type": "address" + } + ], + "name": "ERC20InvalidApprover", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ERC20InvalidReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ERC20InvalidSender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "ERC20InvalidSpender", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "temporaryApprove", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC20Votes.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC20Votes.json new file mode 100644 index 00000000..9f99148d --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC20Votes.json @@ -0,0 +1,778 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ERC20Votes", + "sourceName": "contracts/token/ERC20/extensions/ERC20Votes.sol", + "abi": [ + { + "inputs": [], + "name": "CheckpointUnorderedInsertion", + "type": "error" + }, + { + "inputs": [], + "name": "ECDSAInvalidSignature", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "length", + "type": "uint256" + } + ], + "name": "ECDSAInvalidSignatureLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "ECDSAInvalidSignatureS", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "increasedSupply", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "cap", + "type": "uint256" + } + ], + "name": "ERC20ExceededSafeSupply", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "allowance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + } + ], + "name": "ERC20InsufficientAllowance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + } + ], + "name": "ERC20InsufficientBalance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "approver", + "type": "address" + } + ], + "name": "ERC20InvalidApprover", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ERC20InvalidReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ERC20InvalidSender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "ERC20InvalidSpender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + }, + { + "internalType": "uint48", + "name": "clock", + "type": "uint48" + } + ], + "name": "ERC5805FutureLookup", + "type": "error" + }, + { + "inputs": [], + "name": "ERC6372InconsistentClock", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "currentNonce", + "type": "uint256" + } + ], + "name": "InvalidAccountNonce", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidShortString", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "bits", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "SafeCastOverflowedUintDowncast", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "str", + "type": "string" + } + ], + "name": "StringTooLong", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "expiry", + "type": "uint256" + } + ], + "name": "VotesExpiredSignature", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "delegator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "fromDelegate", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "toDelegate", + "type": "address" + } + ], + "name": "DelegateChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "delegate", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "previousVotes", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newVotes", + "type": "uint256" + } + ], + "name": "DelegateVotesChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "EIP712DomainChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [], + "name": "CLOCK_MODE", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint32", + "name": "pos", + "type": "uint32" + } + ], + "name": "checkpoints", + "outputs": [ + { + "components": [ + { + "internalType": "uint48", + "name": "_key", + "type": "uint48" + }, + { + "internalType": "uint208", + "name": "_value", + "type": "uint208" + } + ], + "internalType": "struct Checkpoints.Checkpoint208", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "clock", + "outputs": [ + { + "internalType": "uint48", + "name": "", + "type": "uint48" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "delegatee", + "type": "address" + } + ], + "name": "delegate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "delegatee", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "expiry", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "delegateBySig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "delegates", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "eip712Domain", + "outputs": [ + { + "internalType": "bytes1", + "name": "fields", + "type": "bytes1" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "version", + "type": "string" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "verifyingContract", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + }, + { + "internalType": "uint256[]", + "name": "extensions", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + } + ], + "name": "getPastTotalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + } + ], + "name": "getPastVotes", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getVotes", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "numCheckpoints", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC20Wrapper.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC20Wrapper.json new file mode 100644 index 00000000..53717244 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC20Wrapper.json @@ -0,0 +1,402 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ERC20Wrapper", + "sourceName": "contracts/token/ERC20/extensions/ERC20Wrapper.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "allowance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + } + ], + "name": "ERC20InsufficientAllowance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + } + ], + "name": "ERC20InsufficientBalance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "approver", + "type": "address" + } + ], + "name": "ERC20InvalidApprover", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ERC20InvalidReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ERC20InvalidSender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "ERC20InvalidSpender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "ERC20InvalidUnderlying", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "SafeERC20FailedOperation", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "depositFor", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "underlying", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "withdrawTo", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC2771Context.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC2771Context.json new file mode 100644 index 00000000..a57e2ab8 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC2771Context.json @@ -0,0 +1,43 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ERC2771Context", + "sourceName": "contracts/metatx/ERC2771Context.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "forwarder", + "type": "address" + } + ], + "name": "isTrustedForwarder", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "trustedForwarder", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC2771Forwarder.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC2771Forwarder.json new file mode 100644 index 00000000..d3d62f6b --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC2771Forwarder.json @@ -0,0 +1,388 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ERC2771Forwarder", + "sourceName": "contracts/metatx/ERC2771Forwarder.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint48", + "name": "deadline", + "type": "uint48" + } + ], + "name": "ERC2771ForwarderExpiredRequest", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "signer", + "type": "address" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + } + ], + "name": "ERC2771ForwarderInvalidSigner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "requestedValue", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "msgValue", + "type": "uint256" + } + ], + "name": "ERC2771ForwarderMismatchedValue", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "address", + "name": "forwarder", + "type": "address" + } + ], + "name": "ERC2771UntrustfulTarget", + "type": "error" + }, + { + "inputs": [], + "name": "FailedCall", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + } + ], + "name": "InsufficientBalance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "currentNonce", + "type": "uint256" + } + ], + "name": "InvalidAccountNonce", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidShortString", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "str", + "type": "string" + } + ], + "name": "StringTooLong", + "type": "error" + }, + { + "anonymous": false, + "inputs": [], + "name": "EIP712DomainChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "signer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "name": "ExecutedForwardRequest", + "type": "event" + }, + { + "inputs": [], + "name": "eip712Domain", + "outputs": [ + { + "internalType": "bytes1", + "name": "fields", + "type": "bytes1" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "version", + "type": "string" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "verifyingContract", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + }, + { + "internalType": "uint256[]", + "name": "extensions", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "gas", + "type": "uint256" + }, + { + "internalType": "uint48", + "name": "deadline", + "type": "uint48" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "internalType": "struct ERC2771Forwarder.ForwardRequestData", + "name": "request", + "type": "tuple" + } + ], + "name": "execute", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "gas", + "type": "uint256" + }, + { + "internalType": "uint48", + "name": "deadline", + "type": "uint48" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "internalType": "struct ERC2771Forwarder.ForwardRequestData[]", + "name": "requests", + "type": "tuple[]" + }, + { + "internalType": "address payable", + "name": "refundReceiver", + "type": "address" + } + ], + "name": "executeBatch", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "gas", + "type": "uint256" + }, + { + "internalType": "uint48", + "name": "deadline", + "type": "uint48" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "internalType": "struct ERC2771Forwarder.ForwardRequestData", + "name": "request", + "type": "tuple" + } + ], + "name": "verify", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x610160604052348015610010575f5ffd5b5060405161133e38038061133e83398101604081905261002f91610189565b6040805180820190915260018152603160f81b60208201528190610053825f6100fd565b610120526100628160016100fd565b61014052815160208084019190912060e052815190820120610100524660a0526100ee60e05161010051604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201529081019290925260608201524660808201523060a08201525f9060c00160405160208183030381529060405280519060200120905090565b60805250503060c052506103cf565b5f602083511015610118576101118361012f565b9050610129565b8161012384826102bd565b5060ff90505b92915050565b5f5f829050601f81511115610162578260405163305a27a960e01b81526004016101599190610377565b60405180910390fd5b805161016d826103ac565b179392505050565b634e487b7160e01b5f52604160045260245ffd5b5f60208284031215610199575f5ffd5b81516001600160401b038111156101ae575f5ffd5b8201601f810184136101be575f5ffd5b80516001600160401b038111156101d7576101d7610175565b604051601f8201601f19908116603f011681016001600160401b038111828210171561020557610205610175565b60405281815282820160200186101561021c575f5ffd5b8160208401602083015e5f91810160200191909152949350505050565b600181811c9082168061024d57607f821691505b60208210810361026b57634e487b7160e01b5f52602260045260245ffd5b50919050565b601f8211156102b857805f5260205f20601f840160051c810160208510156102965750805b601f840160051c820191505b818110156102b5575f81556001016102a2565b50505b505050565b81516001600160401b038111156102d6576102d6610175565b6102ea816102e48454610239565b84610271565b6020601f82116001811461031c575f83156103055750848201515b5f19600385901b1c1916600184901b1784556102b5565b5f84815260208120601f198516915b8281101561034b578785015182556020948501946001909201910161032b565b508482101561036857868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b8051602080830151919081101561026b575f1960209190910360031b1b16919050565b60805160a05160c05160e051610100516101205161014051610f1e6104205f395f61039e01525f61036d01525f610a9601525f610a6e01525f6109c901525f6109f301525f610a1d0152610f1e5ff3fe608060405260043610610049575f3560e01c806319d8d38c1461004d5780637ecebe001461008157806384b0196e146100c3578063ccf96b4a146100ea578063df905caf146100ff575b5f5ffd5b348015610058575f5ffd5b5061006c610067366004610bd5565b610112565b60405190151581526020015b60405180910390f35b34801561008c575f5ffd5b506100b561009b366004610c27565b6001600160a01b03165f9081526002602052604090205490565b604051908152602001610078565b3480156100ce575f5ffd5b506100d7610142565b6040516100789796959493929190610c70565b6100fd6100f8366004610d06565b610184565b005b6100fd61010d366004610bd5565b610289565b5f5f5f5f61011f856102e4565b509250925092508280156101305750815b80156101395750805b95945050505050565b5f6060805f5f5f6060610153610366565b61015b610397565b604080515f80825260208201909252600f60f81b9b939a50919850469750309650945092509050565b6001600160a01b038116155f80805b85811015610242578686828181106101ad576101ad610d88565b90506020028101906101bf9190610d9c565b6101cd906040013584610dba565b92505f6101fd8888848181106101e5576101e5610d88565b90506020028101906101f79190610d9c565b866103c4565b9050806102395787878381811061021657610216610d88565b90506020028101906102289190610d9c565b610236906040013584610dba565b92505b50600101610193565b50348214610271576040516370647f7960e01b8152600481018390523460248201526044015b60405180910390fd5b801561028157610281848261059f565b505050505050565b806040013534146102b957604080516370647f7960e01b8152908201356004820152346024820152604401610268565b6102c48160016103c4565b6102e15760405163d6bda27560e01b815260040160405180910390fd5b50565b5f5f5f5f5f5f6102f387610631565b909250905061031061030b6040890160208a01610c27565b6107a3565b4261032160a08a0160808b01610dd9565b65ffffffffffff161015838015610355575061034060208a018a610c27565b6001600160a01b0316836001600160a01b0316145b919750955093509150509193509193565b60606103927f00000000000000000000000000000000000000000000000000000000000000005f61081c565b905090565b60606103927f0000000000000000000000000000000000000000000000000000000000000000600161081c565b5f5f5f5f5f6103d2876102e4565b935093509350935085156104985783610420576103f56040880160208901610c27565b60405163d2650cd160e01b81526001600160a01b039091166004820152306024820152604401610268565b826104595761043560a0880160808901610dd9565b604051634a777ac560e11b815265ffffffffffff9091166004820152602401610268565b81610498578061046c6020890189610c27565b604051636422d02b60e11b81526001600160a01b03928316600482015291166024820152604401610268565b8380156104a25750815b80156104ab5750825b15610595576001600160a01b0381165f908152600260205260408120805460018101909155905060608801355f6104e860408b0160208c01610c27565b905060408a01355f6104fd60a08d018d610dfe565b61050a60208f018f610c27565b60405160200161051c93929190610e48565b60405160208183030381529060405290505f5f5f83516020850186888af19a505a9050610549818e6108c7565b604080518781528c151560208201526001600160a01b038916917f842fb24a83793558587a3dab2be7674da4a51d09c5542d6dd354e5d0ea70813c910160405180910390a25050505050505b5050505092915050565b804710156105c95760405163cf47918160e01b815247600482015260248101829052604401610268565b5f5f836001600160a01b0316836040515f6040518083038185875af1925050503d805f8114610613576040519150601f19603f3d011682016040523d82523d5f602084013e610618565b606091505b50915091508161062b5761062b816108e3565b50505050565b5f80808061077e61064560c0870187610dfe565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061077892507f7f96328b83274ebc7c1cf4f7a3abda602b51a78b7fa1d86a2ce353d75e587cac91506106ac905060208a018a610c27565b6106bc60408b0160208c01610c27565b60408b013560608c01356106d661009b60208f018f610c27565b8d60800160208101906106e99190610dd9565b8e8060a001906106f99190610dfe565b604051610707929190610e6e565b6040805191829003822060208301999099526001600160a01b0397881690820152959094166060860152608085019290925260a084015260c083015265ffffffffffff1660e0820152610100810191909152610120016040516020818303038152906040528051906020012061090b565b90610937565b5090925090505f81600381111561079757610797610e7d565b14959194509092505050565b6040513060248201525f90819060440160408051601f19818403018152919052602080820180516001600160e01b031663572b6c0560e01b17815282519293505f928392839290918391895afa92503d91505f519050828015610807575060208210155b801561081257505f81115b9695505050505050565b606060ff83146108365761082f83610980565b90506108c1565b81805461084290610e91565b80601f016020809104026020016040519081016040528092919081815260200182805461086e90610e91565b80156108b95780601f10610890576101008083540402835291602001916108b9565b820191905f5260205f20905b81548152906001019060200180831161089c57829003601f168201915b505050505090505b92915050565b6108d6603f6060830135610ec9565b8210156108df57fe5b5050565b8051156108f257805160208201fd5b60405163d6bda27560e01b815260040160405180910390fd5b5f6108c16109176109bd565b8360405161190160f01b8152600281019290925260228201526042902090565b5f5f5f835160410361096e576020840151604085015160608601515f1a61096088828585610ae6565b955095509550505050610979565b505081515f91506002905b9250925092565b60605f61098c83610bae565b6040805160208082528183019092529192505f91906020820181803683375050509182525060208101929092525090565b5f306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148015610a1557507f000000000000000000000000000000000000000000000000000000000000000046145b15610a3f57507f000000000000000000000000000000000000000000000000000000000000000090565b610392604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201527f0000000000000000000000000000000000000000000000000000000000000000918101919091527f000000000000000000000000000000000000000000000000000000000000000060608201524660808201523060a08201525f9060c00160405160208183030381529060405280519060200120905090565b5f80807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0841115610b1f57505f91506003905082610ba4565b604080515f808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa158015610b70573d5f5f3e3d5ffd5b5050604051601f1901519150506001600160a01b038116610b9b57505f925060019150829050610ba4565b92505f91508190505b9450945094915050565b5f60ff8216601f8111156108c157604051632cd44ac360e21b815260040160405180910390fd5b5f60208284031215610be5575f5ffd5b813567ffffffffffffffff811115610bfb575f5ffd5b820160e08185031215610c0c575f5ffd5b9392505050565b6001600160a01b03811681146102e1575f5ffd5b5f60208284031215610c37575f5ffd5b8135610c0c81610c13565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b60ff60f81b8816815260e060208201525f610c8e60e0830189610c42565b8281036040840152610ca08189610c42565b606084018890526001600160a01b038716608085015260a0840186905283810360c0850152845180825260208087019350909101905f5b81811015610cf5578351835260209384019390920191600101610cd7565b50909b9a5050505050505050505050565b5f5f5f60408486031215610d18575f5ffd5b833567ffffffffffffffff811115610d2e575f5ffd5b8401601f81018613610d3e575f5ffd5b803567ffffffffffffffff811115610d54575f5ffd5b8660208260051b8401011115610d68575f5ffd5b602091820194509250840135610d7d81610c13565b809150509250925092565b634e487b7160e01b5f52603260045260245ffd5b5f823560de19833603018112610db0575f5ffd5b9190910192915050565b808201808211156108c157634e487b7160e01b5f52601160045260245ffd5b5f60208284031215610de9575f5ffd5b813565ffffffffffff81168114610c0c575f5ffd5b5f5f8335601e19843603018112610e13575f5ffd5b83018035915067ffffffffffffffff821115610e2d575f5ffd5b602001915036819003821315610e41575f5ffd5b9250929050565b8284823760609190911b6bffffffffffffffffffffffff19169101908152601401919050565b818382375f9101908152919050565b634e487b7160e01b5f52602160045260245ffd5b600181811c90821680610ea557607f821691505b602082108103610ec357634e487b7160e01b5f52602260045260245ffd5b50919050565b5f82610ee357634e487b7160e01b5f52601260045260245ffd5b50049056fea2646970667358221220e39b6e9937121a96227f1ae9eaefb0e9e68f19060317ca7328b85909793b8b5364736f6c634300081b0033", + "deployedBytecode": "0x608060405260043610610049575f3560e01c806319d8d38c1461004d5780637ecebe001461008157806384b0196e146100c3578063ccf96b4a146100ea578063df905caf146100ff575b5f5ffd5b348015610058575f5ffd5b5061006c610067366004610bd5565b610112565b60405190151581526020015b60405180910390f35b34801561008c575f5ffd5b506100b561009b366004610c27565b6001600160a01b03165f9081526002602052604090205490565b604051908152602001610078565b3480156100ce575f5ffd5b506100d7610142565b6040516100789796959493929190610c70565b6100fd6100f8366004610d06565b610184565b005b6100fd61010d366004610bd5565b610289565b5f5f5f5f61011f856102e4565b509250925092508280156101305750815b80156101395750805b95945050505050565b5f6060805f5f5f6060610153610366565b61015b610397565b604080515f80825260208201909252600f60f81b9b939a50919850469750309650945092509050565b6001600160a01b038116155f80805b85811015610242578686828181106101ad576101ad610d88565b90506020028101906101bf9190610d9c565b6101cd906040013584610dba565b92505f6101fd8888848181106101e5576101e5610d88565b90506020028101906101f79190610d9c565b866103c4565b9050806102395787878381811061021657610216610d88565b90506020028101906102289190610d9c565b610236906040013584610dba565b92505b50600101610193565b50348214610271576040516370647f7960e01b8152600481018390523460248201526044015b60405180910390fd5b801561028157610281848261059f565b505050505050565b806040013534146102b957604080516370647f7960e01b8152908201356004820152346024820152604401610268565b6102c48160016103c4565b6102e15760405163d6bda27560e01b815260040160405180910390fd5b50565b5f5f5f5f5f5f6102f387610631565b909250905061031061030b6040890160208a01610c27565b6107a3565b4261032160a08a0160808b01610dd9565b65ffffffffffff161015838015610355575061034060208a018a610c27565b6001600160a01b0316836001600160a01b0316145b919750955093509150509193509193565b60606103927f00000000000000000000000000000000000000000000000000000000000000005f61081c565b905090565b60606103927f0000000000000000000000000000000000000000000000000000000000000000600161081c565b5f5f5f5f5f6103d2876102e4565b935093509350935085156104985783610420576103f56040880160208901610c27565b60405163d2650cd160e01b81526001600160a01b039091166004820152306024820152604401610268565b826104595761043560a0880160808901610dd9565b604051634a777ac560e11b815265ffffffffffff9091166004820152602401610268565b81610498578061046c6020890189610c27565b604051636422d02b60e11b81526001600160a01b03928316600482015291166024820152604401610268565b8380156104a25750815b80156104ab5750825b15610595576001600160a01b0381165f908152600260205260408120805460018101909155905060608801355f6104e860408b0160208c01610c27565b905060408a01355f6104fd60a08d018d610dfe565b61050a60208f018f610c27565b60405160200161051c93929190610e48565b60405160208183030381529060405290505f5f5f83516020850186888af19a505a9050610549818e6108c7565b604080518781528c151560208201526001600160a01b038916917f842fb24a83793558587a3dab2be7674da4a51d09c5542d6dd354e5d0ea70813c910160405180910390a25050505050505b5050505092915050565b804710156105c95760405163cf47918160e01b815247600482015260248101829052604401610268565b5f5f836001600160a01b0316836040515f6040518083038185875af1925050503d805f8114610613576040519150601f19603f3d011682016040523d82523d5f602084013e610618565b606091505b50915091508161062b5761062b816108e3565b50505050565b5f80808061077e61064560c0870187610dfe565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061077892507f7f96328b83274ebc7c1cf4f7a3abda602b51a78b7fa1d86a2ce353d75e587cac91506106ac905060208a018a610c27565b6106bc60408b0160208c01610c27565b60408b013560608c01356106d661009b60208f018f610c27565b8d60800160208101906106e99190610dd9565b8e8060a001906106f99190610dfe565b604051610707929190610e6e565b6040805191829003822060208301999099526001600160a01b0397881690820152959094166060860152608085019290925260a084015260c083015265ffffffffffff1660e0820152610100810191909152610120016040516020818303038152906040528051906020012061090b565b90610937565b5090925090505f81600381111561079757610797610e7d565b14959194509092505050565b6040513060248201525f90819060440160408051601f19818403018152919052602080820180516001600160e01b031663572b6c0560e01b17815282519293505f928392839290918391895afa92503d91505f519050828015610807575060208210155b801561081257505f81115b9695505050505050565b606060ff83146108365761082f83610980565b90506108c1565b81805461084290610e91565b80601f016020809104026020016040519081016040528092919081815260200182805461086e90610e91565b80156108b95780601f10610890576101008083540402835291602001916108b9565b820191905f5260205f20905b81548152906001019060200180831161089c57829003601f168201915b505050505090505b92915050565b6108d6603f6060830135610ec9565b8210156108df57fe5b5050565b8051156108f257805160208201fd5b60405163d6bda27560e01b815260040160405180910390fd5b5f6108c16109176109bd565b8360405161190160f01b8152600281019290925260228201526042902090565b5f5f5f835160410361096e576020840151604085015160608601515f1a61096088828585610ae6565b955095509550505050610979565b505081515f91506002905b9250925092565b60605f61098c83610bae565b6040805160208082528183019092529192505f91906020820181803683375050509182525060208101929092525090565b5f306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148015610a1557507f000000000000000000000000000000000000000000000000000000000000000046145b15610a3f57507f000000000000000000000000000000000000000000000000000000000000000090565b610392604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201527f0000000000000000000000000000000000000000000000000000000000000000918101919091527f000000000000000000000000000000000000000000000000000000000000000060608201524660808201523060a08201525f9060c00160405160208183030381529060405280519060200120905090565b5f80807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0841115610b1f57505f91506003905082610ba4565b604080515f808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa158015610b70573d5f5f3e3d5ffd5b5050604051601f1901519150506001600160a01b038116610b9b57505f925060019150829050610ba4565b92505f91508190505b9450945094915050565b5f60ff8216601f8111156108c157604051632cd44ac360e21b815260040160405180910390fd5b5f60208284031215610be5575f5ffd5b813567ffffffffffffffff811115610bfb575f5ffd5b820160e08185031215610c0c575f5ffd5b9392505050565b6001600160a01b03811681146102e1575f5ffd5b5f60208284031215610c37575f5ffd5b8135610c0c81610c13565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b60ff60f81b8816815260e060208201525f610c8e60e0830189610c42565b8281036040840152610ca08189610c42565b606084018890526001600160a01b038716608085015260a0840186905283810360c0850152845180825260208087019350909101905f5b81811015610cf5578351835260209384019390920191600101610cd7565b50909b9a5050505050505050505050565b5f5f5f60408486031215610d18575f5ffd5b833567ffffffffffffffff811115610d2e575f5ffd5b8401601f81018613610d3e575f5ffd5b803567ffffffffffffffff811115610d54575f5ffd5b8660208260051b8401011115610d68575f5ffd5b602091820194509250840135610d7d81610c13565b809150509250925092565b634e487b7160e01b5f52603260045260245ffd5b5f823560de19833603018112610db0575f5ffd5b9190910192915050565b808201808211156108c157634e487b7160e01b5f52601160045260245ffd5b5f60208284031215610de9575f5ffd5b813565ffffffffffff81168114610c0c575f5ffd5b5f5f8335601e19843603018112610e13575f5ffd5b83018035915067ffffffffffffffff821115610e2d575f5ffd5b602001915036819003821315610e41575f5ffd5b9250929050565b8284823760609190911b6bffffffffffffffffffffffff19169101908152601401919050565b818382375f9101908152919050565b634e487b7160e01b5f52602160045260245ffd5b600181811c90821680610ea557607f821691505b602082108103610ec357634e487b7160e01b5f52602260045260245ffd5b50919050565b5f82610ee357634e487b7160e01b5f52601260045260245ffd5b50049056fea2646970667358221220e39b6e9937121a96227f1ae9eaefb0e9e68f19060317ca7328b85909793b8b5364736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC2981.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC2981.json new file mode 100644 index 00000000..641b450f --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC2981.json @@ -0,0 +1,123 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ERC2981", + "sourceName": "contracts/token/common/ERC2981.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "uint256", + "name": "numerator", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "denominator", + "type": "uint256" + } + ], + "name": "ERC2981InvalidDefaultRoyalty", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ERC2981InvalidDefaultRoyaltyReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "numerator", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "denominator", + "type": "uint256" + } + ], + "name": "ERC2981InvalidTokenRoyalty", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ERC2981InvalidTokenRoyaltyReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "salePrice", + "type": "uint256" + } + ], + "name": "royaltyInfo", + "outputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC4337Utils.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC4337Utils.json new file mode 100644 index 00000000..516b29eb --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC4337Utils.json @@ -0,0 +1,10 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ERC4337Utils", + "sourceName": "contracts/account/utils/draft-ERC4337Utils.sol", + "abi": [], + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212202b11cc99a7bb10d988a6e48c249efa23f66811a64fdfaaa7ec7e348e95cc8deb64736f6c634300081b0033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212202b11cc99a7bb10d988a6e48c249efa23f66811a64fdfaaa7ec7e348e95cc8deb64736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC4626.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC4626.json new file mode 100644 index 00000000..02cfeabf --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC4626.json @@ -0,0 +1,804 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ERC4626", + "sourceName": "contracts/token/ERC20/extensions/ERC4626.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "allowance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + } + ], + "name": "ERC20InsufficientAllowance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + } + ], + "name": "ERC20InsufficientBalance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "approver", + "type": "address" + } + ], + "name": "ERC20InvalidApprover", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ERC20InvalidReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ERC20InvalidSender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "ERC20InvalidSpender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "assets", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "max", + "type": "uint256" + } + ], + "name": "ERC4626ExceededMaxDeposit", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "max", + "type": "uint256" + } + ], + "name": "ERC4626ExceededMaxMint", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "max", + "type": "uint256" + } + ], + "name": "ERC4626ExceededMaxRedeem", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "assets", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "max", + "type": "uint256" + } + ], + "name": "ERC4626ExceededMaxWithdraw", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "SafeERC20FailedOperation", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "Deposit", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "Withdraw", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "asset", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "convertToAssets", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "name": "convertToShares", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "assets", + "type": "uint256" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "deposit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "maxDeposit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "maxMint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "maxRedeem", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "maxWithdraw", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "name": "previewDeposit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "previewMint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "previewRedeem", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "name": "previewWithdraw", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "redeem", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalAssets", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "assets", + "type": "uint256" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "withdraw", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC6909.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC6909.json new file mode 100644 index 00000000..15a37556 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC6909.json @@ -0,0 +1,412 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ERC6909", + "sourceName": "contracts/token/ERC6909/draft-ERC6909.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "allowance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "ERC6909InsufficientAllowance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "ERC6909InsufficientBalance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "approver", + "type": "address" + } + ], + "name": "ERC6909InvalidApprover", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ERC6909InvalidReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ERC6909InvalidSender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "ERC6909InvalidSpender", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "OperatorSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "isOperator", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setOperator", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x6080604052348015600e575f5ffd5b506108368061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610084575f3560e01c8063558a729711610058578063558a7297146100f7578063598af9e71461010a578063b6363cf214610149578063fe99049a14610184575f5ffd5b8062fdd58e1461008857806301ffc9a7146100ae578063095bcdb6146100d1578063426a8493146100e4575b5f5ffd5b61009b610096366004610678565b610197565b6040519081526020015b60405180910390f35b6100c16100bc3660046106a0565b6101bf565b60405190151581526020016100a5565b6100c16100df3660046106ce565b6101f3565b6100c16100f23660046106ce565b61020a565b6100c16101053660046106fe565b610217565b61009b610118366004610737565b6001600160a01b039283165f9081526002602090815260408083209490951682529283528381209181529152205490565b6100c1610157366004610771565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205460ff1690565b6100c16101923660046107a2565b61022c565b6001600160a01b0382165f908152602081815260408083208484529091529020545b92915050565b5f6001600160e01b03198216630f632fb360e01b14806101b957506301ffc9a760e01b6001600160e01b03198316146101b9565b5f61020033858585610295565b5060019392505050565b5f610200338585856102fe565b5f6102233384846103bd565b50600192915050565b5f336001600160a01b038616811480159061026c57506001600160a01b038087165f9081526001602090815260408083209385168352929052205460ff16155b1561027d5761027d8682868661047b565b61028986868686610295565b50600195945050505050565b6001600160a01b0384166102c3576040516301486a4160e71b81525f60048201526024015b60405180910390fd5b6001600160a01b0383166102ec57604051630b8bbd6160e41b81525f60048201526024016102ba565b6102f88484848461052b565b50505050565b6001600160a01b0384166103275760405163198ecd5360e31b81525f60048201526024016102ba565b6001600160a01b03831661035057604051636f65f46560e01b81525f60048201526024016102ba565b6001600160a01b038481165f8181526002602090815260408083209488168084529482528083208784528252918290208590559051848152859392917fb3fd5071835887567a0671151121894ddccc2842f1d10bedad13e0d17cace9a7910160405180910390a450505050565b6001600160a01b0383166103e65760405163198ecd5360e31b81525f60048201526024016102ba565b6001600160a01b03821661040f57604051636f65f46560e01b81525f60048201526024016102ba565b6001600160a01b038381165f81815260016020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527fceb576d9f15e4e200fdb5096d64d5dfd667e16def20c1eefd14256d8e3faa267910160405180910390a3505050565b6001600160a01b038481165f9081526002602090815260408083209387168352928152828220858352905220545f1981101561052457818110156104f257604051632c51fead60e11b81526001600160a01b03851660048201526024810182905260448101839052606481018490526084016102ba565b6001600160a01b038086165f908152600260209081526040808320938816835292815282822086835290522082820390555b5050505050565b336001600160a01b038516156105c4576001600160a01b0385165f908152602081815260408083208684529091529020548281101561059d576040516302c6d3fb60e61b81526001600160a01b03871660048201526024810182905260448101849052606481018590526084016102ba565b6001600160a01b0386165f9081526020818152604080832087845290915290209083900390555b6001600160a01b03841615610609576001600160a01b0384165f90815260208181526040808320868452909152812080548492906106039084906107e1565b90915550505b604080516001600160a01b03838116825260208201859052859281881692918916917f1b3d7edb2e9c0b0e7c525b20aaaef0f5940d2ed71663c7d39266ecafac728859910160405180910390a45050505050565b80356001600160a01b0381168114610673575f5ffd5b919050565b5f5f60408385031215610689575f5ffd5b6106928361065d565b946020939093013593505050565b5f602082840312156106b0575f5ffd5b81356001600160e01b0319811681146106c7575f5ffd5b9392505050565b5f5f5f606084860312156106e0575f5ffd5b6106e98461065d565b95602085013595506040909401359392505050565b5f5f6040838503121561070f575f5ffd5b6107188361065d565b91506020830135801515811461072c575f5ffd5b809150509250929050565b5f5f5f60608486031215610749575f5ffd5b6107528461065d565b92506107606020850161065d565b929592945050506040919091013590565b5f5f60408385031215610782575f5ffd5b61078b8361065d565b91506107996020840161065d565b90509250929050565b5f5f5f5f608085870312156107b5575f5ffd5b6107be8561065d565b93506107cc6020860161065d565b93969395505050506040820135916060013590565b808201808211156101b957634e487b7160e01b5f52601160045260245ffdfea2646970667358221220c7dfa10f1e4d1485b683d9bba3ea130e0eaf5c5c71767c5cf4987650f2f56be464736f6c634300081b0033", + "deployedBytecode": "0x608060405234801561000f575f5ffd5b5060043610610084575f3560e01c8063558a729711610058578063558a7297146100f7578063598af9e71461010a578063b6363cf214610149578063fe99049a14610184575f5ffd5b8062fdd58e1461008857806301ffc9a7146100ae578063095bcdb6146100d1578063426a8493146100e4575b5f5ffd5b61009b610096366004610678565b610197565b6040519081526020015b60405180910390f35b6100c16100bc3660046106a0565b6101bf565b60405190151581526020016100a5565b6100c16100df3660046106ce565b6101f3565b6100c16100f23660046106ce565b61020a565b6100c16101053660046106fe565b610217565b61009b610118366004610737565b6001600160a01b039283165f9081526002602090815260408083209490951682529283528381209181529152205490565b6100c1610157366004610771565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205460ff1690565b6100c16101923660046107a2565b61022c565b6001600160a01b0382165f908152602081815260408083208484529091529020545b92915050565b5f6001600160e01b03198216630f632fb360e01b14806101b957506301ffc9a760e01b6001600160e01b03198316146101b9565b5f61020033858585610295565b5060019392505050565b5f610200338585856102fe565b5f6102233384846103bd565b50600192915050565b5f336001600160a01b038616811480159061026c57506001600160a01b038087165f9081526001602090815260408083209385168352929052205460ff16155b1561027d5761027d8682868661047b565b61028986868686610295565b50600195945050505050565b6001600160a01b0384166102c3576040516301486a4160e71b81525f60048201526024015b60405180910390fd5b6001600160a01b0383166102ec57604051630b8bbd6160e41b81525f60048201526024016102ba565b6102f88484848461052b565b50505050565b6001600160a01b0384166103275760405163198ecd5360e31b81525f60048201526024016102ba565b6001600160a01b03831661035057604051636f65f46560e01b81525f60048201526024016102ba565b6001600160a01b038481165f8181526002602090815260408083209488168084529482528083208784528252918290208590559051848152859392917fb3fd5071835887567a0671151121894ddccc2842f1d10bedad13e0d17cace9a7910160405180910390a450505050565b6001600160a01b0383166103e65760405163198ecd5360e31b81525f60048201526024016102ba565b6001600160a01b03821661040f57604051636f65f46560e01b81525f60048201526024016102ba565b6001600160a01b038381165f81815260016020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527fceb576d9f15e4e200fdb5096d64d5dfd667e16def20c1eefd14256d8e3faa267910160405180910390a3505050565b6001600160a01b038481165f9081526002602090815260408083209387168352928152828220858352905220545f1981101561052457818110156104f257604051632c51fead60e11b81526001600160a01b03851660048201526024810182905260448101839052606481018490526084016102ba565b6001600160a01b038086165f908152600260209081526040808320938816835292815282822086835290522082820390555b5050505050565b336001600160a01b038516156105c4576001600160a01b0385165f908152602081815260408083208684529091529020548281101561059d576040516302c6d3fb60e61b81526001600160a01b03871660048201526024810182905260448101849052606481018590526084016102ba565b6001600160a01b0386165f9081526020818152604080832087845290915290209083900390555b6001600160a01b03841615610609576001600160a01b0384165f90815260208181526040808320868452909152812080548492906106039084906107e1565b90915550505b604080516001600160a01b03838116825260208201859052859281881692918916917f1b3d7edb2e9c0b0e7c525b20aaaef0f5940d2ed71663c7d39266ecafac728859910160405180910390a45050505050565b80356001600160a01b0381168114610673575f5ffd5b919050565b5f5f60408385031215610689575f5ffd5b6106928361065d565b946020939093013593505050565b5f602082840312156106b0575f5ffd5b81356001600160e01b0319811681146106c7575f5ffd5b9392505050565b5f5f5f606084860312156106e0575f5ffd5b6106e98461065d565b95602085013595506040909401359392505050565b5f5f6040838503121561070f575f5ffd5b6107188361065d565b91506020830135801515811461072c575f5ffd5b809150509250929050565b5f5f5f60608486031215610749575f5ffd5b6107528461065d565b92506107606020850161065d565b929592945050506040919091013590565b5f5f60408385031215610782575f5ffd5b61078b8361065d565b91506107996020840161065d565b90509250929050565b5f5f5f5f608085870312156107b5575f5ffd5b6107be8561065d565b93506107cc6020860161065d565b93969395505050506040820135916060013590565b808201808211156101b957634e487b7160e01b5f52601160045260245ffdfea2646970667358221220c7dfa10f1e4d1485b683d9bba3ea130e0eaf5c5c71767c5cf4987650f2f56be464736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC6909ContentURI.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC6909ContentURI.json new file mode 100644 index 00000000..a3e4595f --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC6909ContentURI.json @@ -0,0 +1,469 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ERC6909ContentURI", + "sourceName": "contracts/token/ERC6909/extensions/draft-ERC6909ContentURI.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "allowance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "ERC6909InsufficientAllowance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "ERC6909InsufficientBalance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "approver", + "type": "address" + } + ], + "name": "ERC6909InvalidApprover", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ERC6909InvalidReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ERC6909InvalidSender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "ERC6909InvalidSpender", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "ContractURIUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "OperatorSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "value", + "type": "string" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "URI", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "contractURI", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "isOperator", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setOperator", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "tokenURI", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x6080604052348015600e575f5ffd5b50610a278061001c5f395ff3fe608060405234801561000f575f5ffd5b506004361061009a575f3560e01c8063598af9e711610063578063598af9e714610120578063b6363cf21461015f578063c87b56dd1461019a578063e8a3d485146101ba578063fe99049a146101c2575f5ffd5b8062fdd58e1461009e57806301ffc9a7146100c4578063095bcdb6146100e7578063426a8493146100fa578063558a72971461010d575b5f5ffd5b6100b16100ac3660046107e5565b6101d5565b6040519081526020015b60405180910390f35b6100d76100d236600461080d565b6101fd565b60405190151581526020016100bb565b6100d76100f536600461083b565b610231565b6100d761010836600461083b565b610248565b6100d761011b36600461086b565b610255565b6100b161012e3660046108a4565b6001600160a01b039283165f9081526002602090815260408083209490951682529283528381209181529152205490565b6100d761016d3660046108de565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205460ff1690565b6101ad6101a836600461090f565b61026a565b6040516100bb9190610926565b6101ad610309565b6100d76101d036600461095b565b610399565b6001600160a01b0382165f908152602081815260408083208484529091529020545b92915050565b5f6001600160e01b03198216630f632fb360e01b14806101f757506301ffc9a760e01b6001600160e01b03198316146101f7565b5f61023e33858585610402565b5060019392505050565b5f61023e3385858561046b565b5f61026133848461052a565b50600192915050565b5f8181526004602052604090208054606091906102869061099a565b80601f01602080910402602001604051908101604052809291908181526020018280546102b29061099a565b80156102fd5780601f106102d4576101008083540402835291602001916102fd565b820191905f5260205f20905b8154815290600101906020018083116102e057829003601f168201915b50505050509050919050565b6060600380546103189061099a565b80601f01602080910402602001604051908101604052809291908181526020018280546103449061099a565b801561038f5780601f106103665761010080835404028352916020019161038f565b820191905f5260205f20905b81548152906001019060200180831161037257829003601f168201915b5050505050905090565b5f336001600160a01b03861681148015906103d957506001600160a01b038087165f9081526001602090815260408083209385168352929052205460ff16155b156103ea576103ea868286866105e8565b6103f686868686610402565b50600195945050505050565b6001600160a01b038416610430576040516301486a4160e71b81525f60048201526024015b60405180910390fd5b6001600160a01b03831661045957604051630b8bbd6160e41b81525f6004820152602401610427565b61046584848484610698565b50505050565b6001600160a01b0384166104945760405163198ecd5360e31b81525f6004820152602401610427565b6001600160a01b0383166104bd57604051636f65f46560e01b81525f6004820152602401610427565b6001600160a01b038481165f8181526002602090815260408083209488168084529482528083208784528252918290208590559051848152859392917fb3fd5071835887567a0671151121894ddccc2842f1d10bedad13e0d17cace9a7910160405180910390a450505050565b6001600160a01b0383166105535760405163198ecd5360e31b81525f6004820152602401610427565b6001600160a01b03821661057c57604051636f65f46560e01b81525f6004820152602401610427565b6001600160a01b038381165f81815260016020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527fceb576d9f15e4e200fdb5096d64d5dfd667e16def20c1eefd14256d8e3faa267910160405180910390a3505050565b6001600160a01b038481165f9081526002602090815260408083209387168352928152828220858352905220545f19811015610691578181101561065f57604051632c51fead60e11b81526001600160a01b0385166004820152602481018290526044810183905260648101849052608401610427565b6001600160a01b038086165f908152600260209081526040808320938816835292815282822086835290522082820390555b5050505050565b336001600160a01b03851615610731576001600160a01b0385165f908152602081815260408083208684529091529020548281101561070a576040516302c6d3fb60e61b81526001600160a01b0387166004820152602481018290526044810184905260648101859052608401610427565b6001600160a01b0386165f9081526020818152604080832087845290915290209083900390555b6001600160a01b03841615610776576001600160a01b0384165f90815260208181526040808320868452909152812080548492906107709084906109d2565b90915550505b604080516001600160a01b03838116825260208201859052859281881692918916917f1b3d7edb2e9c0b0e7c525b20aaaef0f5940d2ed71663c7d39266ecafac728859910160405180910390a45050505050565b80356001600160a01b03811681146107e0575f5ffd5b919050565b5f5f604083850312156107f6575f5ffd5b6107ff836107ca565b946020939093013593505050565b5f6020828403121561081d575f5ffd5b81356001600160e01b031981168114610834575f5ffd5b9392505050565b5f5f5f6060848603121561084d575f5ffd5b610856846107ca565b95602085013595506040909401359392505050565b5f5f6040838503121561087c575f5ffd5b610885836107ca565b915060208301358015158114610899575f5ffd5b809150509250929050565b5f5f5f606084860312156108b6575f5ffd5b6108bf846107ca565b92506108cd602085016107ca565b929592945050506040919091013590565b5f5f604083850312156108ef575f5ffd5b6108f8836107ca565b9150610906602084016107ca565b90509250929050565b5f6020828403121561091f575f5ffd5b5035919050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f5f5f5f6080858703121561096e575f5ffd5b610977856107ca565b9350610985602086016107ca565b93969395505050506040820135916060013590565b600181811c908216806109ae57607f821691505b6020821081036109cc57634e487b7160e01b5f52602260045260245ffd5b50919050565b808201808211156101f757634e487b7160e01b5f52601160045260245ffdfea26469706673582212200ad49e11fdf6c1e3df0a5de1d5fba7e0f77e6cc1cdad549e25fffc34573b2b1f64736f6c634300081b0033", + "deployedBytecode": "0x608060405234801561000f575f5ffd5b506004361061009a575f3560e01c8063598af9e711610063578063598af9e714610120578063b6363cf21461015f578063c87b56dd1461019a578063e8a3d485146101ba578063fe99049a146101c2575f5ffd5b8062fdd58e1461009e57806301ffc9a7146100c4578063095bcdb6146100e7578063426a8493146100fa578063558a72971461010d575b5f5ffd5b6100b16100ac3660046107e5565b6101d5565b6040519081526020015b60405180910390f35b6100d76100d236600461080d565b6101fd565b60405190151581526020016100bb565b6100d76100f536600461083b565b610231565b6100d761010836600461083b565b610248565b6100d761011b36600461086b565b610255565b6100b161012e3660046108a4565b6001600160a01b039283165f9081526002602090815260408083209490951682529283528381209181529152205490565b6100d761016d3660046108de565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205460ff1690565b6101ad6101a836600461090f565b61026a565b6040516100bb9190610926565b6101ad610309565b6100d76101d036600461095b565b610399565b6001600160a01b0382165f908152602081815260408083208484529091529020545b92915050565b5f6001600160e01b03198216630f632fb360e01b14806101f757506301ffc9a760e01b6001600160e01b03198316146101f7565b5f61023e33858585610402565b5060019392505050565b5f61023e3385858561046b565b5f61026133848461052a565b50600192915050565b5f8181526004602052604090208054606091906102869061099a565b80601f01602080910402602001604051908101604052809291908181526020018280546102b29061099a565b80156102fd5780601f106102d4576101008083540402835291602001916102fd565b820191905f5260205f20905b8154815290600101906020018083116102e057829003601f168201915b50505050509050919050565b6060600380546103189061099a565b80601f01602080910402602001604051908101604052809291908181526020018280546103449061099a565b801561038f5780601f106103665761010080835404028352916020019161038f565b820191905f5260205f20905b81548152906001019060200180831161037257829003601f168201915b5050505050905090565b5f336001600160a01b03861681148015906103d957506001600160a01b038087165f9081526001602090815260408083209385168352929052205460ff16155b156103ea576103ea868286866105e8565b6103f686868686610402565b50600195945050505050565b6001600160a01b038416610430576040516301486a4160e71b81525f60048201526024015b60405180910390fd5b6001600160a01b03831661045957604051630b8bbd6160e41b81525f6004820152602401610427565b61046584848484610698565b50505050565b6001600160a01b0384166104945760405163198ecd5360e31b81525f6004820152602401610427565b6001600160a01b0383166104bd57604051636f65f46560e01b81525f6004820152602401610427565b6001600160a01b038481165f8181526002602090815260408083209488168084529482528083208784528252918290208590559051848152859392917fb3fd5071835887567a0671151121894ddccc2842f1d10bedad13e0d17cace9a7910160405180910390a450505050565b6001600160a01b0383166105535760405163198ecd5360e31b81525f6004820152602401610427565b6001600160a01b03821661057c57604051636f65f46560e01b81525f6004820152602401610427565b6001600160a01b038381165f81815260016020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527fceb576d9f15e4e200fdb5096d64d5dfd667e16def20c1eefd14256d8e3faa267910160405180910390a3505050565b6001600160a01b038481165f9081526002602090815260408083209387168352928152828220858352905220545f19811015610691578181101561065f57604051632c51fead60e11b81526001600160a01b0385166004820152602481018290526044810183905260648101849052608401610427565b6001600160a01b038086165f908152600260209081526040808320938816835292815282822086835290522082820390555b5050505050565b336001600160a01b03851615610731576001600160a01b0385165f908152602081815260408083208684529091529020548281101561070a576040516302c6d3fb60e61b81526001600160a01b0387166004820152602481018290526044810184905260648101859052608401610427565b6001600160a01b0386165f9081526020818152604080832087845290915290209083900390555b6001600160a01b03841615610776576001600160a01b0384165f90815260208181526040808320868452909152812080548492906107709084906109d2565b90915550505b604080516001600160a01b03838116825260208201859052859281881692918916917f1b3d7edb2e9c0b0e7c525b20aaaef0f5940d2ed71663c7d39266ecafac728859910160405180910390a45050505050565b80356001600160a01b03811681146107e0575f5ffd5b919050565b5f5f604083850312156107f6575f5ffd5b6107ff836107ca565b946020939093013593505050565b5f6020828403121561081d575f5ffd5b81356001600160e01b031981168114610834575f5ffd5b9392505050565b5f5f5f6060848603121561084d575f5ffd5b610856846107ca565b95602085013595506040909401359392505050565b5f5f6040838503121561087c575f5ffd5b610885836107ca565b915060208301358015158114610899575f5ffd5b809150509250929050565b5f5f5f606084860312156108b6575f5ffd5b6108bf846107ca565b92506108cd602085016107ca565b929592945050506040919091013590565b5f5f604083850312156108ef575f5ffd5b6108f8836107ca565b9150610906602084016107ca565b90509250929050565b5f6020828403121561091f575f5ffd5b5035919050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f5f5f5f6080858703121561096e575f5ffd5b610977856107ca565b9350610985602086016107ca565b93969395505050506040820135916060013590565b600181811c908216806109ae57607f821691505b6020821081036109cc57634e487b7160e01b5f52602260045260245ffd5b50919050565b808201808211156101f757634e487b7160e01b5f52601160045260245ffdfea26469706673582212200ad49e11fdf6c1e3df0a5de1d5fba7e0f77e6cc1cdad549e25fffc34573b2b1f64736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC6909Metadata.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC6909Metadata.json new file mode 100644 index 00000000..779594bd --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC6909Metadata.json @@ -0,0 +1,526 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ERC6909Metadata", + "sourceName": "contracts/token/ERC6909/extensions/draft-ERC6909Metadata.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "allowance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "ERC6909InsufficientAllowance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "ERC6909InsufficientBalance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "approver", + "type": "address" + } + ], + "name": "ERC6909InvalidApprover", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ERC6909InvalidReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ERC6909InvalidSender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "ERC6909InvalidSpender", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "newDecimals", + "type": "uint8" + } + ], + "name": "ERC6909DecimalsUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "newName", + "type": "string" + } + ], + "name": "ERC6909NameUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "newSymbol", + "type": "string" + } + ], + "name": "ERC6909SymbolUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "OperatorSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "isOperator", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setOperator", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x6080604052348015600e575f5ffd5b50610a068061001c5f395ff3fe608060405234801561000f575f5ffd5b50600436106100a4575f3560e01c8063426a84931161006e578063426a84931461015f5780634e41a1fb14610172578063558a729714610185578063598af9e714610198578063b6363cf2146101d7578063fe99049a14610212575f5ffd5b8062ad800c146100a8578062fdd58e146100d157806301ffc9a7146100f2578063095bcdb6146101155780633f47e66214610128575b5f5ffd5b6100bb6100b63660046107a9565b610225565b6040516100c891906107c0565b60405180910390f35b6100e46100df366004610810565b6102c4565b6040519081526020016100c8565b610105610100366004610838565b6102ec565b60405190151581526020016100c8565b610105610123366004610866565b610320565b61014d6101363660046107a9565b5f9081526003602052604090206002015460ff1690565b60405160ff90911681526020016100c8565b61010561016d366004610866565b610337565b6100bb6101803660046107a9565b610344565b610105610193366004610896565b610363565b6100e46101a63660046108cf565b6001600160a01b039283165f9081526002602090815260408083209490951682529283528381209181529152205490565b6101056101e5366004610909565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205460ff1690565b61010561022036600461093a565b610378565b5f81815260036020526040902080546060919061024190610979565b80601f016020809104026020016040519081016040528092919081815260200182805461026d90610979565b80156102b85780601f1061028f576101008083540402835291602001916102b8565b820191905f5260205f20905b81548152906001019060200180831161029b57829003601f168201915b50505050509050919050565b6001600160a01b0382165f908152602081815260408083208484529091529020545b92915050565b5f6001600160e01b03198216630f632fb360e01b14806102e657506301ffc9a760e01b6001600160e01b03198316146102e6565b5f61032d338585856103e1565b5060019392505050565b5f61032d3385858561044a565b5f81815260036020526040902060010180546060919061024190610979565b5f61036f338484610509565b50600192915050565b5f336001600160a01b03861681148015906103b857506001600160a01b038087165f9081526001602090815260408083209385168352929052205460ff16155b156103c9576103c9868286866105c7565b6103d5868686866103e1565b50600195945050505050565b6001600160a01b03841661040f576040516301486a4160e71b81525f60048201526024015b60405180910390fd5b6001600160a01b03831661043857604051630b8bbd6160e41b81525f6004820152602401610406565b61044484848484610677565b50505050565b6001600160a01b0384166104735760405163198ecd5360e31b81525f6004820152602401610406565b6001600160a01b03831661049c57604051636f65f46560e01b81525f6004820152602401610406565b6001600160a01b038481165f8181526002602090815260408083209488168084529482528083208784528252918290208590559051848152859392917fb3fd5071835887567a0671151121894ddccc2842f1d10bedad13e0d17cace9a7910160405180910390a450505050565b6001600160a01b0383166105325760405163198ecd5360e31b81525f6004820152602401610406565b6001600160a01b03821661055b57604051636f65f46560e01b81525f6004820152602401610406565b6001600160a01b038381165f81815260016020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527fceb576d9f15e4e200fdb5096d64d5dfd667e16def20c1eefd14256d8e3faa267910160405180910390a3505050565b6001600160a01b038481165f9081526002602090815260408083209387168352928152828220858352905220545f19811015610670578181101561063e57604051632c51fead60e11b81526001600160a01b0385166004820152602481018290526044810183905260648101849052608401610406565b6001600160a01b038086165f908152600260209081526040808320938816835292815282822086835290522082820390555b5050505050565b336001600160a01b03851615610710576001600160a01b0385165f90815260208181526040808320868452909152902054828110156106e9576040516302c6d3fb60e61b81526001600160a01b0387166004820152602481018290526044810184905260648101859052608401610406565b6001600160a01b0386165f9081526020818152604080832087845290915290209083900390555b6001600160a01b03841615610755576001600160a01b0384165f908152602081815260408083208684529091528120805484929061074f9084906109b1565b90915550505b604080516001600160a01b03838116825260208201859052859281881692918916917f1b3d7edb2e9c0b0e7c525b20aaaef0f5940d2ed71663c7d39266ecafac728859910160405180910390a45050505050565b5f602082840312156107b9575f5ffd5b5035919050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b80356001600160a01b038116811461080b575f5ffd5b919050565b5f5f60408385031215610821575f5ffd5b61082a836107f5565b946020939093013593505050565b5f60208284031215610848575f5ffd5b81356001600160e01b03198116811461085f575f5ffd5b9392505050565b5f5f5f60608486031215610878575f5ffd5b610881846107f5565b95602085013595506040909401359392505050565b5f5f604083850312156108a7575f5ffd5b6108b0836107f5565b9150602083013580151581146108c4575f5ffd5b809150509250929050565b5f5f5f606084860312156108e1575f5ffd5b6108ea846107f5565b92506108f8602085016107f5565b929592945050506040919091013590565b5f5f6040838503121561091a575f5ffd5b610923836107f5565b9150610931602084016107f5565b90509250929050565b5f5f5f5f6080858703121561094d575f5ffd5b610956856107f5565b9350610964602086016107f5565b93969395505050506040820135916060013590565b600181811c9082168061098d57607f821691505b6020821081036109ab57634e487b7160e01b5f52602260045260245ffd5b50919050565b808201808211156102e657634e487b7160e01b5f52601160045260245ffdfea2646970667358221220cbc19250a8a47770f647ef9bfcc586eeaa11d0c767d0985a092d0b025dd9927664736f6c634300081b0033", + "deployedBytecode": "0x608060405234801561000f575f5ffd5b50600436106100a4575f3560e01c8063426a84931161006e578063426a84931461015f5780634e41a1fb14610172578063558a729714610185578063598af9e714610198578063b6363cf2146101d7578063fe99049a14610212575f5ffd5b8062ad800c146100a8578062fdd58e146100d157806301ffc9a7146100f2578063095bcdb6146101155780633f47e66214610128575b5f5ffd5b6100bb6100b63660046107a9565b610225565b6040516100c891906107c0565b60405180910390f35b6100e46100df366004610810565b6102c4565b6040519081526020016100c8565b610105610100366004610838565b6102ec565b60405190151581526020016100c8565b610105610123366004610866565b610320565b61014d6101363660046107a9565b5f9081526003602052604090206002015460ff1690565b60405160ff90911681526020016100c8565b61010561016d366004610866565b610337565b6100bb6101803660046107a9565b610344565b610105610193366004610896565b610363565b6100e46101a63660046108cf565b6001600160a01b039283165f9081526002602090815260408083209490951682529283528381209181529152205490565b6101056101e5366004610909565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205460ff1690565b61010561022036600461093a565b610378565b5f81815260036020526040902080546060919061024190610979565b80601f016020809104026020016040519081016040528092919081815260200182805461026d90610979565b80156102b85780601f1061028f576101008083540402835291602001916102b8565b820191905f5260205f20905b81548152906001019060200180831161029b57829003601f168201915b50505050509050919050565b6001600160a01b0382165f908152602081815260408083208484529091529020545b92915050565b5f6001600160e01b03198216630f632fb360e01b14806102e657506301ffc9a760e01b6001600160e01b03198316146102e6565b5f61032d338585856103e1565b5060019392505050565b5f61032d3385858561044a565b5f81815260036020526040902060010180546060919061024190610979565b5f61036f338484610509565b50600192915050565b5f336001600160a01b03861681148015906103b857506001600160a01b038087165f9081526001602090815260408083209385168352929052205460ff16155b156103c9576103c9868286866105c7565b6103d5868686866103e1565b50600195945050505050565b6001600160a01b03841661040f576040516301486a4160e71b81525f60048201526024015b60405180910390fd5b6001600160a01b03831661043857604051630b8bbd6160e41b81525f6004820152602401610406565b61044484848484610677565b50505050565b6001600160a01b0384166104735760405163198ecd5360e31b81525f6004820152602401610406565b6001600160a01b03831661049c57604051636f65f46560e01b81525f6004820152602401610406565b6001600160a01b038481165f8181526002602090815260408083209488168084529482528083208784528252918290208590559051848152859392917fb3fd5071835887567a0671151121894ddccc2842f1d10bedad13e0d17cace9a7910160405180910390a450505050565b6001600160a01b0383166105325760405163198ecd5360e31b81525f6004820152602401610406565b6001600160a01b03821661055b57604051636f65f46560e01b81525f6004820152602401610406565b6001600160a01b038381165f81815260016020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527fceb576d9f15e4e200fdb5096d64d5dfd667e16def20c1eefd14256d8e3faa267910160405180910390a3505050565b6001600160a01b038481165f9081526002602090815260408083209387168352928152828220858352905220545f19811015610670578181101561063e57604051632c51fead60e11b81526001600160a01b0385166004820152602481018290526044810183905260648101849052608401610406565b6001600160a01b038086165f908152600260209081526040808320938816835292815282822086835290522082820390555b5050505050565b336001600160a01b03851615610710576001600160a01b0385165f90815260208181526040808320868452909152902054828110156106e9576040516302c6d3fb60e61b81526001600160a01b0387166004820152602481018290526044810184905260648101859052608401610406565b6001600160a01b0386165f9081526020818152604080832087845290915290209083900390555b6001600160a01b03841615610755576001600160a01b0384165f908152602081815260408083208684529091528120805484929061074f9084906109b1565b90915550505b604080516001600160a01b03838116825260208201859052859281881692918916917f1b3d7edb2e9c0b0e7c525b20aaaef0f5940d2ed71663c7d39266ecafac728859910160405180910390a45050505050565b5f602082840312156107b9575f5ffd5b5035919050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b80356001600160a01b038116811461080b575f5ffd5b919050565b5f5f60408385031215610821575f5ffd5b61082a836107f5565b946020939093013593505050565b5f60208284031215610848575f5ffd5b81356001600160e01b03198116811461085f575f5ffd5b9392505050565b5f5f5f60608486031215610878575f5ffd5b610881846107f5565b95602085013595506040909401359392505050565b5f5f604083850312156108a7575f5ffd5b6108b0836107f5565b9150602083013580151581146108c4575f5ffd5b809150509250929050565b5f5f5f606084860312156108e1575f5ffd5b6108ea846107f5565b92506108f8602085016107f5565b929592945050506040919091013590565b5f5f6040838503121561091a575f5ffd5b610923836107f5565b9150610931602084016107f5565b90509250929050565b5f5f5f5f6080858703121561094d575f5ffd5b610956856107f5565b9350610964602086016107f5565b93969395505050506040820135916060013590565b600181811c9082168061098d57607f821691505b6020821081036109ab57634e487b7160e01b5f52602260045260245ffd5b50919050565b808201808211156102e657634e487b7160e01b5f52601160045260245ffdfea2646970667358221220cbc19250a8a47770f647ef9bfcc586eeaa11d0c767d0985a092d0b025dd9927664736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC6909TokenSupply.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC6909TokenSupply.json new file mode 100644 index 00000000..e1d438c4 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC6909TokenSupply.json @@ -0,0 +1,431 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ERC6909TokenSupply", + "sourceName": "contracts/token/ERC6909/extensions/draft-ERC6909TokenSupply.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "allowance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "ERC6909InsufficientAllowance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "ERC6909InsufficientBalance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "approver", + "type": "address" + } + ], + "name": "ERC6909InvalidApprover", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ERC6909InvalidReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ERC6909InvalidSender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "ERC6909InvalidSpender", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "OperatorSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "isOperator", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setOperator", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x6080604052348015600e575f5ffd5b506108dc8061001c5f395ff3fe608060405234801561000f575f5ffd5b506004361061008f575f3560e01c8063558a729711610063578063558a729714610102578063598af9e714610115578063b6363cf214610154578063bd85b0391461018f578063fe99049a146101ae575f5ffd5b8062fdd58e1461009357806301ffc9a7146100b9578063095bcdb6146100dc578063426a8493146100ef575b5f5ffd5b6100a66100a1366004610707565b6101c1565b6040519081526020015b60405180910390f35b6100cc6100c736600461072f565b6101e9565b60405190151581526020016100b0565b6100cc6100ea36600461075d565b61021d565b6100cc6100fd36600461075d565b610234565b6100cc61011036600461078d565b610241565b6100a66101233660046107c6565b6001600160a01b039283165f9081526002602090815260408083209490951682529283528381209181529152205490565b6100cc610162366004610800565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205460ff1690565b6100a661019d366004610831565b5f9081526003602052604090205490565b6100cc6101bc366004610848565b610256565b6001600160a01b0382165f908152602081815260408083208484529091529020545b92915050565b5f6001600160e01b03198216630f632fb360e01b14806101e357506301ffc9a760e01b6001600160e01b03198316146101e3565b5f61022a338585856102bf565b5060019392505050565b5f61022a33858585610328565b5f61024d3384846103e7565b50600192915050565b5f336001600160a01b038616811480159061029657506001600160a01b038087165f9081526001602090815260408083209385168352929052205460ff16155b156102a7576102a7868286866104a5565b6102b3868686866102bf565b50600195945050505050565b6001600160a01b0384166102ed576040516301486a4160e71b81525f60048201526024015b60405180910390fd5b6001600160a01b03831661031657604051630b8bbd6160e41b81525f60048201526024016102e4565b61032284848484610555565b50505050565b6001600160a01b0384166103515760405163198ecd5360e31b81525f60048201526024016102e4565b6001600160a01b03831661037a57604051636f65f46560e01b81525f60048201526024016102e4565b6001600160a01b038481165f8181526002602090815260408083209488168084529482528083208784528252918290208590559051848152859392917fb3fd5071835887567a0671151121894ddccc2842f1d10bedad13e0d17cace9a7910160405180910390a450505050565b6001600160a01b0383166104105760405163198ecd5360e31b81525f60048201526024016102e4565b6001600160a01b03821661043957604051636f65f46560e01b81525f60048201526024016102e4565b6001600160a01b038381165f81815260016020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527fceb576d9f15e4e200fdb5096d64d5dfd667e16def20c1eefd14256d8e3faa267910160405180910390a3505050565b6001600160a01b038481165f9081526002602090815260408083209387168352928152828220858352905220545f1981101561054e578181101561051c57604051632c51fead60e11b81526001600160a01b03851660048201526024810182905260448101839052606481018490526084016102e4565b6001600160a01b038086165f908152600260209081526040808320938816835292815282822086835290522082820390555b5050505050565b610561848484846105ba565b6001600160a01b038416610592575f828152600360205260408120805483929061058c908490610887565b90915550505b6001600160a01b038316610322575f8281526003602052604090208054829003905550505050565b336001600160a01b03851615610653576001600160a01b0385165f908152602081815260408083208684529091529020548281101561062c576040516302c6d3fb60e61b81526001600160a01b03871660048201526024810182905260448101849052606481018590526084016102e4565b6001600160a01b0386165f9081526020818152604080832087845290915290209083900390555b6001600160a01b03841615610698576001600160a01b0384165f9081526020818152604080832086845290915281208054849290610692908490610887565b90915550505b604080516001600160a01b03838116825260208201859052859281881692918916917f1b3d7edb2e9c0b0e7c525b20aaaef0f5940d2ed71663c7d39266ecafac728859910160405180910390a45050505050565b80356001600160a01b0381168114610702575f5ffd5b919050565b5f5f60408385031215610718575f5ffd5b610721836106ec565b946020939093013593505050565b5f6020828403121561073f575f5ffd5b81356001600160e01b031981168114610756575f5ffd5b9392505050565b5f5f5f6060848603121561076f575f5ffd5b610778846106ec565b95602085013595506040909401359392505050565b5f5f6040838503121561079e575f5ffd5b6107a7836106ec565b9150602083013580151581146107bb575f5ffd5b809150509250929050565b5f5f5f606084860312156107d8575f5ffd5b6107e1846106ec565b92506107ef602085016106ec565b929592945050506040919091013590565b5f5f60408385031215610811575f5ffd5b61081a836106ec565b9150610828602084016106ec565b90509250929050565b5f60208284031215610841575f5ffd5b5035919050565b5f5f5f5f6080858703121561085b575f5ffd5b610864856106ec565b9350610872602086016106ec565b93969395505050506040820135916060013590565b808201808211156101e357634e487b7160e01b5f52601160045260245ffdfea26469706673582212201d349892e68b770a5541ac2632ed70e132e0f50aef68ba240ec667617979db4764736f6c634300081b0033", + "deployedBytecode": "0x608060405234801561000f575f5ffd5b506004361061008f575f3560e01c8063558a729711610063578063558a729714610102578063598af9e714610115578063b6363cf214610154578063bd85b0391461018f578063fe99049a146101ae575f5ffd5b8062fdd58e1461009357806301ffc9a7146100b9578063095bcdb6146100dc578063426a8493146100ef575b5f5ffd5b6100a66100a1366004610707565b6101c1565b6040519081526020015b60405180910390f35b6100cc6100c736600461072f565b6101e9565b60405190151581526020016100b0565b6100cc6100ea36600461075d565b61021d565b6100cc6100fd36600461075d565b610234565b6100cc61011036600461078d565b610241565b6100a66101233660046107c6565b6001600160a01b039283165f9081526002602090815260408083209490951682529283528381209181529152205490565b6100cc610162366004610800565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205460ff1690565b6100a661019d366004610831565b5f9081526003602052604090205490565b6100cc6101bc366004610848565b610256565b6001600160a01b0382165f908152602081815260408083208484529091529020545b92915050565b5f6001600160e01b03198216630f632fb360e01b14806101e357506301ffc9a760e01b6001600160e01b03198316146101e3565b5f61022a338585856102bf565b5060019392505050565b5f61022a33858585610328565b5f61024d3384846103e7565b50600192915050565b5f336001600160a01b038616811480159061029657506001600160a01b038087165f9081526001602090815260408083209385168352929052205460ff16155b156102a7576102a7868286866104a5565b6102b3868686866102bf565b50600195945050505050565b6001600160a01b0384166102ed576040516301486a4160e71b81525f60048201526024015b60405180910390fd5b6001600160a01b03831661031657604051630b8bbd6160e41b81525f60048201526024016102e4565b61032284848484610555565b50505050565b6001600160a01b0384166103515760405163198ecd5360e31b81525f60048201526024016102e4565b6001600160a01b03831661037a57604051636f65f46560e01b81525f60048201526024016102e4565b6001600160a01b038481165f8181526002602090815260408083209488168084529482528083208784528252918290208590559051848152859392917fb3fd5071835887567a0671151121894ddccc2842f1d10bedad13e0d17cace9a7910160405180910390a450505050565b6001600160a01b0383166104105760405163198ecd5360e31b81525f60048201526024016102e4565b6001600160a01b03821661043957604051636f65f46560e01b81525f60048201526024016102e4565b6001600160a01b038381165f81815260016020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527fceb576d9f15e4e200fdb5096d64d5dfd667e16def20c1eefd14256d8e3faa267910160405180910390a3505050565b6001600160a01b038481165f9081526002602090815260408083209387168352928152828220858352905220545f1981101561054e578181101561051c57604051632c51fead60e11b81526001600160a01b03851660048201526024810182905260448101839052606481018490526084016102e4565b6001600160a01b038086165f908152600260209081526040808320938816835292815282822086835290522082820390555b5050505050565b610561848484846105ba565b6001600160a01b038416610592575f828152600360205260408120805483929061058c908490610887565b90915550505b6001600160a01b038316610322575f8281526003602052604090208054829003905550505050565b336001600160a01b03851615610653576001600160a01b0385165f908152602081815260408083208684529091529020548281101561062c576040516302c6d3fb60e61b81526001600160a01b03871660048201526024810182905260448101849052606481018590526084016102e4565b6001600160a01b0386165f9081526020818152604080832087845290915290209083900390555b6001600160a01b03841615610698576001600160a01b0384165f9081526020818152604080832086845290915281208054849290610692908490610887565b90915550505b604080516001600160a01b03838116825260208201859052859281881692918916917f1b3d7edb2e9c0b0e7c525b20aaaef0f5940d2ed71663c7d39266ecafac728859910160405180910390a45050505050565b80356001600160a01b0381168114610702575f5ffd5b919050565b5f5f60408385031215610718575f5ffd5b610721836106ec565b946020939093013593505050565b5f6020828403121561073f575f5ffd5b81356001600160e01b031981168114610756575f5ffd5b9392505050565b5f5f5f6060848603121561076f575f5ffd5b610778846106ec565b95602085013595506040909401359392505050565b5f5f6040838503121561079e575f5ffd5b6107a7836106ec565b9150602083013580151581146107bb575f5ffd5b809150509250929050565b5f5f5f606084860312156107d8575f5ffd5b6107e1846106ec565b92506107ef602085016106ec565b929592945050506040919091013590565b5f5f60408385031215610811575f5ffd5b61081a836106ec565b9150610828602084016106ec565b90509250929050565b5f60208284031215610841575f5ffd5b5035919050565b5f5f5f5f6080858703121561085b575f5ffd5b610864856106ec565b9350610872602086016106ec565b93969395505050506040820135916060013590565b808201808211156101e357634e487b7160e01b5f52601160045260245ffdfea26469706673582212201d349892e68b770a5541ac2632ed70e132e0f50aef68ba240ec667617979db4764736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC721.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC721.json new file mode 100644 index 00000000..c546e806 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC721.json @@ -0,0 +1,444 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ERC721", + "sourceName": "contracts/token/ERC721/ERC721.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "ERC721IncorrectOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ERC721InsufficientApproval", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "approver", + "type": "address" + } + ], + "name": "ERC721InvalidApprover", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "ERC721InvalidOperator", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "ERC721InvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ERC721InvalidReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ERC721InvalidSender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ERC721NonexistentToken", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "approved", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "ApprovalForAll", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "getApproved", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "isApprovedForAll", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ownerOf", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setApprovalForAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "tokenURI", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC721Burnable.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC721Burnable.json new file mode 100644 index 00000000..8aaeaaa7 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC721Burnable.json @@ -0,0 +1,457 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ERC721Burnable", + "sourceName": "contracts/token/ERC721/extensions/ERC721Burnable.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "ERC721IncorrectOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ERC721InsufficientApproval", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "approver", + "type": "address" + } + ], + "name": "ERC721InvalidApprover", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "ERC721InvalidOperator", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "ERC721InvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ERC721InvalidReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ERC721InvalidSender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ERC721NonexistentToken", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "approved", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "ApprovalForAll", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "getApproved", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "isApprovedForAll", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ownerOf", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setApprovalForAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "tokenURI", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC721Consecutive.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC721Consecutive.json new file mode 100644 index 00000000..d6de42cc --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC721Consecutive.json @@ -0,0 +1,506 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ERC721Consecutive", + "sourceName": "contracts/token/ERC721/extensions/ERC721Consecutive.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "uint256", + "name": "batchSize", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxBatch", + "type": "uint256" + } + ], + "name": "ERC721ExceededMaxBatchMint", + "type": "error" + }, + { + "inputs": [], + "name": "ERC721ForbiddenBatchBurn", + "type": "error" + }, + { + "inputs": [], + "name": "ERC721ForbiddenBatchMint", + "type": "error" + }, + { + "inputs": [], + "name": "ERC721ForbiddenMint", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "ERC721IncorrectOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ERC721InsufficientApproval", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "approver", + "type": "address" + } + ], + "name": "ERC721InvalidApprover", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "ERC721InvalidOperator", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "ERC721InvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ERC721InvalidReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ERC721InvalidSender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ERC721NonexistentToken", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "approved", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "ApprovalForAll", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "fromTokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "toTokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "fromAddress", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "toAddress", + "type": "address" + } + ], + "name": "ConsecutiveTransfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "getApproved", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "isApprovedForAll", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ownerOf", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setApprovalForAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "tokenURI", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC721Enumerable.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC721Enumerable.json new file mode 100644 index 00000000..adfbaaaf --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC721Enumerable.json @@ -0,0 +1,521 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ERC721Enumerable", + "sourceName": "contracts/token/ERC721/extensions/ERC721Enumerable.sol", + "abi": [ + { + "inputs": [], + "name": "ERC721EnumerableForbiddenBatchMint", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "ERC721IncorrectOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ERC721InsufficientApproval", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "approver", + "type": "address" + } + ], + "name": "ERC721InvalidApprover", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "ERC721InvalidOperator", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "ERC721InvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ERC721InvalidReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ERC721InvalidSender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ERC721NonexistentToken", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "ERC721OutOfBoundsIndex", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "approved", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "ApprovalForAll", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "getApproved", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "isApprovedForAll", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ownerOf", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setApprovalForAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "tokenByIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "tokenOfOwnerByIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "tokenURI", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC721Holder.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC721Holder.json new file mode 100644 index 00000000..869877c3 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC721Holder.json @@ -0,0 +1,45 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ERC721Holder", + "sourceName": "contracts/token/ERC721/utils/ERC721Holder.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC721Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC721Pausable.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC721Pausable.json new file mode 100644 index 00000000..099a81a1 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC721Pausable.json @@ -0,0 +1,493 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ERC721Pausable", + "sourceName": "contracts/token/ERC721/extensions/ERC721Pausable.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "ERC721IncorrectOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ERC721InsufficientApproval", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "approver", + "type": "address" + } + ], + "name": "ERC721InvalidApprover", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "ERC721InvalidOperator", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "ERC721InvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ERC721InvalidReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ERC721InvalidSender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ERC721NonexistentToken", + "type": "error" + }, + { + "inputs": [], + "name": "EnforcedPause", + "type": "error" + }, + { + "inputs": [], + "name": "ExpectedPause", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "approved", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "ApprovalForAll", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "getApproved", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "isApprovedForAll", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ownerOf", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setApprovalForAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "tokenURI", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC721Royalty.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC721Royalty.json new file mode 100644 index 00000000..d86a1624 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC721Royalty.json @@ -0,0 +1,537 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ERC721Royalty", + "sourceName": "contracts/token/ERC721/extensions/ERC721Royalty.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "uint256", + "name": "numerator", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "denominator", + "type": "uint256" + } + ], + "name": "ERC2981InvalidDefaultRoyalty", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ERC2981InvalidDefaultRoyaltyReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "numerator", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "denominator", + "type": "uint256" + } + ], + "name": "ERC2981InvalidTokenRoyalty", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ERC2981InvalidTokenRoyaltyReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "ERC721IncorrectOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ERC721InsufficientApproval", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "approver", + "type": "address" + } + ], + "name": "ERC721InvalidApprover", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "ERC721InvalidOperator", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "ERC721InvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ERC721InvalidReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ERC721InvalidSender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ERC721NonexistentToken", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "approved", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "ApprovalForAll", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "getApproved", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "isApprovedForAll", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ownerOf", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "salePrice", + "type": "uint256" + } + ], + "name": "royaltyInfo", + "outputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setApprovalForAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "tokenURI", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC721URIStorage.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC721URIStorage.json new file mode 100644 index 00000000..253fd9db --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC721URIStorage.json @@ -0,0 +1,476 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ERC721URIStorage", + "sourceName": "contracts/token/ERC721/extensions/ERC721URIStorage.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "ERC721IncorrectOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ERC721InsufficientApproval", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "approver", + "type": "address" + } + ], + "name": "ERC721InvalidApprover", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "ERC721InvalidOperator", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "ERC721InvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ERC721InvalidReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ERC721InvalidSender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ERC721NonexistentToken", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "approved", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "ApprovalForAll", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "_fromTokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_toTokenId", + "type": "uint256" + } + ], + "name": "BatchMetadataUpdate", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "MetadataUpdate", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "getApproved", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "isApprovedForAll", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ownerOf", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setApprovalForAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "tokenURI", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC721Utils.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC721Utils.json new file mode 100644 index 00000000..c0b70316 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC721Utils.json @@ -0,0 +1,10 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ERC721Utils", + "sourceName": "contracts/token/ERC721/utils/ERC721Utils.sol", + "abi": [], + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220734e123a65c4f93119e23537b7a93433e029bbd9a6148485aca5f5b8a0f6447364736f6c634300081b0033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220734e123a65c4f93119e23537b7a93433e029bbd9a6148485aca5f5b8a0f6447364736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC721Votes.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC721Votes.json new file mode 100644 index 00000000..a11f4911 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC721Votes.json @@ -0,0 +1,832 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ERC721Votes", + "sourceName": "contracts/token/ERC721/extensions/ERC721Votes.sol", + "abi": [ + { + "inputs": [], + "name": "CheckpointUnorderedInsertion", + "type": "error" + }, + { + "inputs": [], + "name": "ECDSAInvalidSignature", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "length", + "type": "uint256" + } + ], + "name": "ECDSAInvalidSignatureLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "ECDSAInvalidSignatureS", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + }, + { + "internalType": "uint48", + "name": "clock", + "type": "uint48" + } + ], + "name": "ERC5805FutureLookup", + "type": "error" + }, + { + "inputs": [], + "name": "ERC6372InconsistentClock", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "ERC721IncorrectOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ERC721InsufficientApproval", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "approver", + "type": "address" + } + ], + "name": "ERC721InvalidApprover", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "ERC721InvalidOperator", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "ERC721InvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ERC721InvalidReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ERC721InvalidSender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ERC721NonexistentToken", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "currentNonce", + "type": "uint256" + } + ], + "name": "InvalidAccountNonce", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidShortString", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "bits", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "SafeCastOverflowedUintDowncast", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "str", + "type": "string" + } + ], + "name": "StringTooLong", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "expiry", + "type": "uint256" + } + ], + "name": "VotesExpiredSignature", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "approved", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "ApprovalForAll", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "delegator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "fromDelegate", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "toDelegate", + "type": "address" + } + ], + "name": "DelegateChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "delegate", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "previousVotes", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newVotes", + "type": "uint256" + } + ], + "name": "DelegateVotesChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "EIP712DomainChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [], + "name": "CLOCK_MODE", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "clock", + "outputs": [ + { + "internalType": "uint48", + "name": "", + "type": "uint48" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "delegatee", + "type": "address" + } + ], + "name": "delegate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "delegatee", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "expiry", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "delegateBySig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "delegates", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "eip712Domain", + "outputs": [ + { + "internalType": "bytes1", + "name": "fields", + "type": "bytes1" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "version", + "type": "string" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "verifyingContract", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + }, + { + "internalType": "uint256[]", + "name": "extensions", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "getApproved", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + } + ], + "name": "getPastTotalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + } + ], + "name": "getPastVotes", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getVotes", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "isApprovedForAll", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ownerOf", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setApprovalForAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "tokenURI", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC721Wrapper.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC721Wrapper.json new file mode 100644 index 00000000..b2386224 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC721Wrapper.json @@ -0,0 +1,550 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ERC721Wrapper", + "sourceName": "contracts/token/ERC721/extensions/ERC721Wrapper.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "ERC721IncorrectOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ERC721InsufficientApproval", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "approver", + "type": "address" + } + ], + "name": "ERC721InvalidApprover", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "ERC721InvalidOperator", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "ERC721InvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ERC721InvalidReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ERC721InvalidSender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ERC721NonexistentToken", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "ERC721UnsupportedToken", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "approved", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "ApprovalForAll", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "tokenIds", + "type": "uint256[]" + } + ], + "name": "depositFor", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "getApproved", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "isApprovedForAll", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC721Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ownerOf", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setApprovalForAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "tokenURI", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "underlying", + "outputs": [ + { + "internalType": "contract IERC721", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "tokenIds", + "type": "uint256[]" + } + ], + "name": "withdrawTo", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC7579Utils.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC7579Utils.json new file mode 100644 index 00000000..1db33c5e --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC7579Utils.json @@ -0,0 +1,116 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ERC7579Utils", + "sourceName": "contracts/account/utils/draft-ERC7579Utils.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "uint256", + "name": "moduleTypeId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "module", + "type": "address" + } + ], + "name": "ERC7579AlreadyInstalledModule", + "type": "error" + }, + { + "inputs": [], + "name": "ERC7579DecodingError", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "moduleTypeId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "module", + "type": "address" + } + ], + "name": "ERC7579MismatchedModuleTypeId", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "moduleTypeId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "module", + "type": "address" + } + ], + "name": "ERC7579UninstalledModule", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "CallType", + "name": "callType", + "type": "bytes1" + } + ], + "name": "ERC7579UnsupportedCallType", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "ExecType", + "name": "execType", + "type": "bytes1" + } + ], + "name": "ERC7579UnsupportedExecType", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "moduleTypeId", + "type": "uint256" + } + ], + "name": "ERC7579UnsupportedModuleType", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "batchExecutionIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "returndata", + "type": "bytes" + } + ], + "name": "ERC7579TryExecuteFail", + "type": "event" + } + ], + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220db3a72b9c30031607ba89d7eb8369ee2e926ab5d5c33a06523b63949a7fe2a4264736f6c634300081b0033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220db3a72b9c30031607ba89d7eb8369ee2e926ab5d5c33a06523b63949a7fe2a4264736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC7739.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC7739.json new file mode 100644 index 00000000..5fbd1968 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC7739.json @@ -0,0 +1,100 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ERC7739", + "sourceName": "contracts/utils/cryptography/signers/draft-ERC7739.sol", + "abi": [ + { + "inputs": [], + "name": "InvalidShortString", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "str", + "type": "string" + } + ], + "name": "StringTooLong", + "type": "error" + }, + { + "anonymous": false, + "inputs": [], + "name": "EIP712DomainChanged", + "type": "event" + }, + { + "inputs": [], + "name": "eip712Domain", + "outputs": [ + { + "internalType": "bytes1", + "name": "fields", + "type": "bytes1" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "version", + "type": "string" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "verifyingContract", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + }, + { + "internalType": "uint256[]", + "name": "extensions", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "isValidSignature", + "outputs": [ + { + "internalType": "bytes4", + "name": "result", + "type": "bytes4" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC7739Utils.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC7739Utils.json new file mode 100644 index 00000000..ae4c1f0b --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC7739Utils.json @@ -0,0 +1,10 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ERC7739Utils", + "sourceName": "contracts/utils/cryptography/draft-ERC7739Utils.sol", + "abi": [], + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220fc5562afd1633c482567d7fc4a88e684cfbe6b4857d996b10f32ac98c45b7f7f64736f6c634300081b0033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220fc5562afd1633c482567d7fc4a88e684cfbe6b4857d996b10f32ac98c45b7f7f64736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC7821.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC7821.json new file mode 100644 index 00000000..6f31d16c --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC7821.json @@ -0,0 +1,109 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ERC7821", + "sourceName": "contracts/account/extensions/draft-ERC7821.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "AccountUnauthorized", + "type": "error" + }, + { + "inputs": [], + "name": "ERC7579DecodingError", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "ExecType", + "name": "execType", + "type": "bytes1" + } + ], + "name": "ERC7579UnsupportedExecType", + "type": "error" + }, + { + "inputs": [], + "name": "FailedCall", + "type": "error" + }, + { + "inputs": [], + "name": "OutOfRangeAccess", + "type": "error" + }, + { + "inputs": [], + "name": "UnsupportedExecutionMode", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "batchExecutionIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "returndata", + "type": "bytes" + } + ], + "name": "ERC7579TryExecuteFail", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "mode", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "executionData", + "type": "bytes" + } + ], + "name": "execute", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "mode", + "type": "bytes32" + } + ], + "name": "supportsExecutionMode", + "outputs": [ + { + "internalType": "bool", + "name": "result", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC7913P256Verifier.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC7913P256Verifier.json new file mode 100644 index 00000000..2e44fc71 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC7913P256Verifier.json @@ -0,0 +1,40 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ERC7913P256Verifier", + "sourceName": "contracts/utils/cryptography/verifiers/ERC7913P256Verifier.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "bytes", + "name": "key", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "verify", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x6080604052348015600e575f5ffd5b50610c0e8061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610029575f3560e01c8063024ad3181461002d575b5f5ffd5b61004061003b366004610ac8565b61005d565b6040516001600160e01b0319909116815260200160405180910390f35b5f60408514801561006f575060408210155b15610104575f610082602082888a610b41565b61008b91610b68565b90505f61009c60406020898b610b41565b6100a591610b68565b90505f6100b56020828789610b41565b6100be91610b68565b90505f6100cf60406020888a610b41565b6100d891610b68565b90506100e78883838787610118565b156100ff575062495a6360e31b935061010f92505050565b505050505b506001600160e01b03195b95945050505050565b5f5f5f6101288888888888610151565b91509150806101435761013e888888888861022c565b610145565b815b98975050505050505050565b5f5f61015d86866102dc565b1580610170575061016e8484610338565b155b1561018057505f90506001610222565b61018d878787878761039c565b1561019d57506001905080610222565b61020c7fbb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023600560017fa71af64de5126a4a4e02b7922d66ce9415ce88a4c9d25514d91082c8725ac9577f5d47723c8fbe580bb369fec9c2665d8e30a435b9932645482e7c9f11e872296b61039c565b1561021c57505f90506001610222565b505f9050805b9550959350505050565b5f61023785856102dc565b158061024a57506102488383610338565b155b1561025657505f61010f565b5f61026184846103dc565b90505f61027b865f516020610bb95f395f51905f526105cf565b90505f5f516020610bb95f395f51905f52828a0990505f5f516020610bb95f395f51905f52838a0990505f6102b18584846105de565b509050896102cc5f516020610bb95f395f51905f5283610b85565b149b9a5050505050505050505050565b5f82158015906102f857505f516020610bb95f395f51905f5283105b801561030357508115155b801561032f57507f7fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a88211155b90505b92915050565b5f600160601b63ffffffff60c01b031980838409817f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b8387856003600160601b0363ffffffff60c01b0319878b8c0908090894821191909310169190921416919050565b5f6040518681528560208201528460408201528360608201528260808201525f5f5260205f60a0836101005afa6103cf57fe5b50505f5195945050505050565b6103e4610a3c565b60405180606001604052805f81526020015f81526020015f815250815f6010811061041157610411610ba4565b6020020181905250604051806060016040528084815260200183815260200160018152508160016010811061044857610448610ba4565b602002018190525060405180606001604052807f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29681526020017f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f581526020016001815250816004601081106104bf576104bf610ba4565b60200201526104d58160015b6020020151610702565b60408201526104e58160046104cb565b6101008201526020810151610502908260025b602002015161075e565b606082015261051b8160015b60200201518260046104f8565b60a082015261052b81600261050e565b60c082015261053b81600361050e565b60e08201526105548160015b60200201518260086104f8565b610120820152610565816002610547565b610140820152610576816003610547565b610160820152610587816004610547565b6101808201526105a18160015b602002015182600c6104f8565b6101a08201526105b2816002610594565b6101c08201526105c3816003610594565b6101e082015292915050565b5f61032f8360028403846107bc565b5f80808080805b60808110156106e6578115610619576105ff8484846107dd565b919550935091506106118484846107dd565b919550935091505b600c60fc89901c1660fe88901c1789816010811061063957610639610ba4565b602002015160400151156106d257825f036106a85789816010811061066057610660610ba4565b6020020151518a826010811061067857610678610ba4565b6020020151602001518b836010811061069357610693610ba4565b602002015160400151919650945092506106d2565b6106ca8a82601081106106bd576106bd610ba4565b6020020151868686610860565b919650945092505b50600297881b979690961b956001016105e5565b506106f283838361098c565b945094505050505b935093915050565b61072360405180606001604052805f81526020015f81526020015f81525090565b5f5f5f61073c855f0151866020015187604001516107dd565b6040805160608101825293845260208401929092529082015295945050505050565b61077f60405180606001604052805f81526020015f81526020015f81525090565b5f5f5f61079986865f015187602001518860400151610860565b604080516060810182529384526020840192909252908201529695505050505050565b5f5f5f6107ca8686866109d9565b915091508161010f5761010f6012610a2b565b5f5f5f600160601b63ffffffff60c01b031980868709818687098283848384096003600160601b0363ffffffff60c01b03190984858c8d096003090890508283838b09600409838482600209850385848509089650838485858609600809850385868a880385088509089550505050808186880960020991505093509350939050565b5f5f5f600160601b63ffffffff60c01b0319604088015181818209828388858a8b090960208c0151098381850385868686098c090884858a8b098d51098581870387868f09089350811584151680156108c057600181146109065761097b565b868586098788898386096002098903898a848a098b038b88890908089a5087888983890987098903898a8e8c038c8689090887090899505086878c88098609975061097b565b8c8c8c898283098a8283098b8c8d8384096003600160601b0363ffffffff60c01b0319098d8e8889096003090890508b8c83870960040994508b8c866002098d038d838409089e508b8c8384096008098c0391508b8f8d03860894508b828d878409089d505050898a8284096002099a505050505b505050505050509450945094915050565b5f5f825f0361099f57505f9050806106fa565b600160601b63ffffffff60c01b03195f6109b985836105cf565b905081818209828189099450828383830988099350505050935093915050565b5f5f825f036109ec57505f9050806106fa565b60405160208152602080820152602060408201528560608201528460808201528360a082015260205f60c08360055afa9250505f519050935093915050565b634e487b715f52806020526024601cfd5b6040518061020001604052806010905b610a6d60405180606001604052805f81526020015f81526020015f81525090565b815260200190600190039081610a4c5790505090565b5f5f83601f840112610a93575f5ffd5b50813567ffffffffffffffff811115610aaa575f5ffd5b602083019150836020828501011115610ac1575f5ffd5b9250929050565b5f5f5f5f5f60608688031215610adc575f5ffd5b853567ffffffffffffffff811115610af2575f5ffd5b610afe88828901610a83565b90965094505060208601359250604086013567ffffffffffffffff811115610b24575f5ffd5b610b3088828901610a83565b969995985093965092949392505050565b5f5f85851115610b4f575f5ffd5b83861115610b5b575f5ffd5b5050820193919092039150565b80356020831015610332575f19602084900360031b1b1692915050565b5f82610b9f57634e487b7160e01b5f52601260045260245ffd5b500690565b634e487b7160e01b5f52603260045260245ffdfeffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551a26469706673582212209e22d5aa59ce3bde56366d8e1ad4cb51d41e6229bc77b1ce678d31facfcbf9a864736f6c634300081b0033", + "deployedBytecode": "0x608060405234801561000f575f5ffd5b5060043610610029575f3560e01c8063024ad3181461002d575b5f5ffd5b61004061003b366004610ac8565b61005d565b6040516001600160e01b0319909116815260200160405180910390f35b5f60408514801561006f575060408210155b15610104575f610082602082888a610b41565b61008b91610b68565b90505f61009c60406020898b610b41565b6100a591610b68565b90505f6100b56020828789610b41565b6100be91610b68565b90505f6100cf60406020888a610b41565b6100d891610b68565b90506100e78883838787610118565b156100ff575062495a6360e31b935061010f92505050565b505050505b506001600160e01b03195b95945050505050565b5f5f5f6101288888888888610151565b91509150806101435761013e888888888861022c565b610145565b815b98975050505050505050565b5f5f61015d86866102dc565b1580610170575061016e8484610338565b155b1561018057505f90506001610222565b61018d878787878761039c565b1561019d57506001905080610222565b61020c7fbb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023600560017fa71af64de5126a4a4e02b7922d66ce9415ce88a4c9d25514d91082c8725ac9577f5d47723c8fbe580bb369fec9c2665d8e30a435b9932645482e7c9f11e872296b61039c565b1561021c57505f90506001610222565b505f9050805b9550959350505050565b5f61023785856102dc565b158061024a57506102488383610338565b155b1561025657505f61010f565b5f61026184846103dc565b90505f61027b865f516020610bb95f395f51905f526105cf565b90505f5f516020610bb95f395f51905f52828a0990505f5f516020610bb95f395f51905f52838a0990505f6102b18584846105de565b509050896102cc5f516020610bb95f395f51905f5283610b85565b149b9a5050505050505050505050565b5f82158015906102f857505f516020610bb95f395f51905f5283105b801561030357508115155b801561032f57507f7fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a88211155b90505b92915050565b5f600160601b63ffffffff60c01b031980838409817f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b8387856003600160601b0363ffffffff60c01b0319878b8c0908090894821191909310169190921416919050565b5f6040518681528560208201528460408201528360608201528260808201525f5f5260205f60a0836101005afa6103cf57fe5b50505f5195945050505050565b6103e4610a3c565b60405180606001604052805f81526020015f81526020015f815250815f6010811061041157610411610ba4565b6020020181905250604051806060016040528084815260200183815260200160018152508160016010811061044857610448610ba4565b602002018190525060405180606001604052807f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29681526020017f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f581526020016001815250816004601081106104bf576104bf610ba4565b60200201526104d58160015b6020020151610702565b60408201526104e58160046104cb565b6101008201526020810151610502908260025b602002015161075e565b606082015261051b8160015b60200201518260046104f8565b60a082015261052b81600261050e565b60c082015261053b81600361050e565b60e08201526105548160015b60200201518260086104f8565b610120820152610565816002610547565b610140820152610576816003610547565b610160820152610587816004610547565b6101808201526105a18160015b602002015182600c6104f8565b6101a08201526105b2816002610594565b6101c08201526105c3816003610594565b6101e082015292915050565b5f61032f8360028403846107bc565b5f80808080805b60808110156106e6578115610619576105ff8484846107dd565b919550935091506106118484846107dd565b919550935091505b600c60fc89901c1660fe88901c1789816010811061063957610639610ba4565b602002015160400151156106d257825f036106a85789816010811061066057610660610ba4565b6020020151518a826010811061067857610678610ba4565b6020020151602001518b836010811061069357610693610ba4565b602002015160400151919650945092506106d2565b6106ca8a82601081106106bd576106bd610ba4565b6020020151868686610860565b919650945092505b50600297881b979690961b956001016105e5565b506106f283838361098c565b945094505050505b935093915050565b61072360405180606001604052805f81526020015f81526020015f81525090565b5f5f5f61073c855f0151866020015187604001516107dd565b6040805160608101825293845260208401929092529082015295945050505050565b61077f60405180606001604052805f81526020015f81526020015f81525090565b5f5f5f61079986865f015187602001518860400151610860565b604080516060810182529384526020840192909252908201529695505050505050565b5f5f5f6107ca8686866109d9565b915091508161010f5761010f6012610a2b565b5f5f5f600160601b63ffffffff60c01b031980868709818687098283848384096003600160601b0363ffffffff60c01b03190984858c8d096003090890508283838b09600409838482600209850385848509089650838485858609600809850385868a880385088509089550505050808186880960020991505093509350939050565b5f5f5f600160601b63ffffffff60c01b0319604088015181818209828388858a8b090960208c0151098381850385868686098c090884858a8b098d51098581870387868f09089350811584151680156108c057600181146109065761097b565b868586098788898386096002098903898a848a098b038b88890908089a5087888983890987098903898a8e8c038c8689090887090899505086878c88098609975061097b565b8c8c8c898283098a8283098b8c8d8384096003600160601b0363ffffffff60c01b0319098d8e8889096003090890508b8c83870960040994508b8c866002098d038d838409089e508b8c8384096008098c0391508b8f8d03860894508b828d878409089d505050898a8284096002099a505050505b505050505050509450945094915050565b5f5f825f0361099f57505f9050806106fa565b600160601b63ffffffff60c01b03195f6109b985836105cf565b905081818209828189099450828383830988099350505050935093915050565b5f5f825f036109ec57505f9050806106fa565b60405160208152602080820152602060408201528560608201528460808201528360a082015260205f60c08360055afa9250505f519050935093915050565b634e487b715f52806020526024601cfd5b6040518061020001604052806010905b610a6d60405180606001604052805f81526020015f81526020015f81525090565b815260200190600190039081610a4c5790505090565b5f5f83601f840112610a93575f5ffd5b50813567ffffffffffffffff811115610aaa575f5ffd5b602083019150836020828501011115610ac1575f5ffd5b9250929050565b5f5f5f5f5f60608688031215610adc575f5ffd5b853567ffffffffffffffff811115610af2575f5ffd5b610afe88828901610a83565b90965094505060208601359250604086013567ffffffffffffffff811115610b24575f5ffd5b610b3088828901610a83565b969995985093965092949392505050565b5f5f85851115610b4f575f5ffd5b83861115610b5b575f5ffd5b5050820193919092039150565b80356020831015610332575f19602084900360031b1b1692915050565b5f82610b9f57634e487b7160e01b5f52601260045260245ffd5b500690565b634e487b7160e01b5f52603260045260245ffdfeffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551a26469706673582212209e22d5aa59ce3bde56366d8e1ad4cb51d41e6229bc77b1ce678d31facfcbf9a864736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC7913RSAVerifier.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC7913RSAVerifier.json new file mode 100644 index 00000000..821d28de --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ERC7913RSAVerifier.json @@ -0,0 +1,40 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ERC7913RSAVerifier", + "sourceName": "contracts/utils/cryptography/verifiers/ERC7913RSAVerifier.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "bytes", + "name": "key", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "verify", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x6080604052348015600e575f5ffd5b506106c08061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610029575f3560e01c8063024ad3181461002d575b5f5ffd5b61004061003b366004610491565b61005d565b6040516001600160e01b0319909116815260200160405180910390f35b5f808061006c878901896105a9565b915091506100cd8660405160200161008691815260200190565b60408051601f198184030181526020601f8901819004810284018101909252878352919088908890819084018382808284375f920191909152508792508691506100f39050565b6100df576001600160e01b03196100e7565b62495a6360e31b5b98975050505050505050565b5f61014d6002866040516101079190610625565b602060405180830381855afa158015610122573d5f5f3e3d5ffd5b5050506040513d601f19601f820116820180604052508101906101459190610630565b858585610158565b90505b949350505050565b80515f9061010081108061016d575084518114155b1561017b575f915050610150565b5f5b818110156101f2575f610193826020850361033c565b90505f6101a38883016020015190565b90505f6101b38784016020015190565b9050808210156101c5575050506101f2565b808211806101d557506020850383145b156101e7575f95505050505050610150565b50505060200161017d565b505f6101ff86868661034e565b90505f5f5f6102148460328703016020015190565b6001600160f81b031916603160f81b036102595750720181898068304b0432400b281820100828002160651b91506bffffffffffffffffffffffff19905060346102b3565b600f1985850101516001600160f81b031916602f60f81b036102a65750700181798058304b0432400b28182010082160751b91506dffffffffffffffffffffffffffff19905060326102b3565b5f95505050505050610150565b80850360025b818110156102f057602081870101516001600160f81b0319908116146102e8575f975050505050505050610150565b6001016102b9565b5060208501516001600160f01b031916600160f01b14801561031f57508261031b8683016020015190565b1684145b801561032d5750858501518b145b9b9a5050505050505050505050565b5f8282188284100282185b9392505050565b60605f5f61035d868686610379565b91509150816103705761037060126103f0565b95945050505050565b5f606061038583610401565b156103a0575050604080515f808252602082019092526103e8565b8251855185516040516103bf92919084908a908a908a90602001610647565b604051602081830303815290604052915060208201818184518360055afa828452910160405291505b935093915050565b634e487b715f52806020526024601cfd5b5f805b82518110156104435782818151811061041f5761041f610676565b01602001516001600160f81b0319161561043b57505f92915050565b600101610404565b50600192915050565b5f5f83601f84011261045c575f5ffd5b50813567ffffffffffffffff811115610473575f5ffd5b60208301915083602082850101111561048a575f5ffd5b9250929050565b5f5f5f5f5f606086880312156104a5575f5ffd5b853567ffffffffffffffff8111156104bb575f5ffd5b6104c78882890161044c565b90965094505060208601359250604086013567ffffffffffffffff8111156104ed575f5ffd5b6104f98882890161044c565b969995985093965092949392505050565b634e487b7160e01b5f52604160045260245ffd5b5f82601f83011261052d575f5ffd5b813567ffffffffffffffff8111156105475761054761050a565b604051601f8201601f19908116603f0116810167ffffffffffffffff811182821017156105765761057661050a565b60405281815283820160200185101561058d575f5ffd5b816020850160208301375f918101602001919091529392505050565b5f5f604083850312156105ba575f5ffd5b823567ffffffffffffffff8111156105d0575f5ffd5b6105dc8582860161051e565b925050602083013567ffffffffffffffff8111156105f8575f5ffd5b6106048582860161051e565b9150509250929050565b5f81518060208401855e5f93019283525090919050565b5f610347828461060e565b5f60208284031215610640575f5ffd5b5051919050565b8681528560208201528460408201525f6100e761067061066a606085018861060e565b8661060e565b8461060e565b634e487b7160e01b5f52603260045260245ffdfea264697066735822122082a1aebb6c6ad13b2c7af56c970465c4a67cf171cc2d2514a188ed9526c0e6bc64736f6c634300081b0033", + "deployedBytecode": "0x608060405234801561000f575f5ffd5b5060043610610029575f3560e01c8063024ad3181461002d575b5f5ffd5b61004061003b366004610491565b61005d565b6040516001600160e01b0319909116815260200160405180910390f35b5f808061006c878901896105a9565b915091506100cd8660405160200161008691815260200190565b60408051601f198184030181526020601f8901819004810284018101909252878352919088908890819084018382808284375f920191909152508792508691506100f39050565b6100df576001600160e01b03196100e7565b62495a6360e31b5b98975050505050505050565b5f61014d6002866040516101079190610625565b602060405180830381855afa158015610122573d5f5f3e3d5ffd5b5050506040513d601f19601f820116820180604052508101906101459190610630565b858585610158565b90505b949350505050565b80515f9061010081108061016d575084518114155b1561017b575f915050610150565b5f5b818110156101f2575f610193826020850361033c565b90505f6101a38883016020015190565b90505f6101b38784016020015190565b9050808210156101c5575050506101f2565b808211806101d557506020850383145b156101e7575f95505050505050610150565b50505060200161017d565b505f6101ff86868661034e565b90505f5f5f6102148460328703016020015190565b6001600160f81b031916603160f81b036102595750720181898068304b0432400b281820100828002160651b91506bffffffffffffffffffffffff19905060346102b3565b600f1985850101516001600160f81b031916602f60f81b036102a65750700181798058304b0432400b28182010082160751b91506dffffffffffffffffffffffffffff19905060326102b3565b5f95505050505050610150565b80850360025b818110156102f057602081870101516001600160f81b0319908116146102e8575f975050505050505050610150565b6001016102b9565b5060208501516001600160f01b031916600160f01b14801561031f57508261031b8683016020015190565b1684145b801561032d5750858501518b145b9b9a5050505050505050505050565b5f8282188284100282185b9392505050565b60605f5f61035d868686610379565b91509150816103705761037060126103f0565b95945050505050565b5f606061038583610401565b156103a0575050604080515f808252602082019092526103e8565b8251855185516040516103bf92919084908a908a908a90602001610647565b604051602081830303815290604052915060208201818184518360055afa828452910160405291505b935093915050565b634e487b715f52806020526024601cfd5b5f805b82518110156104435782818151811061041f5761041f610676565b01602001516001600160f81b0319161561043b57505f92915050565b600101610404565b50600192915050565b5f5f83601f84011261045c575f5ffd5b50813567ffffffffffffffff811115610473575f5ffd5b60208301915083602082850101111561048a575f5ffd5b9250929050565b5f5f5f5f5f606086880312156104a5575f5ffd5b853567ffffffffffffffff8111156104bb575f5ffd5b6104c78882890161044c565b90965094505060208601359250604086013567ffffffffffffffff8111156104ed575f5ffd5b6104f98882890161044c565b969995985093965092949392505050565b634e487b7160e01b5f52604160045260245ffd5b5f82601f83011261052d575f5ffd5b813567ffffffffffffffff8111156105475761054761050a565b604051601f8201601f19908116603f0116810167ffffffffffffffff811182821017156105765761057661050a565b60405281815283820160200185101561058d575f5ffd5b816020850160208301375f918101602001919091529392505050565b5f5f604083850312156105ba575f5ffd5b823567ffffffffffffffff8111156105d0575f5ffd5b6105dc8582860161051e565b925050602083013567ffffffffffffffff8111156105f8575f5ffd5b6106048582860161051e565b9150509250929050565b5f81518060208401855e5f93019283525090919050565b5f610347828461060e565b5f60208284031215610640575f5ffd5b5051919050565b8681528560208201528460408201525f6100e761067061066a606085018861060e565b8661060e565b8461060e565b634e487b7160e01b5f52603260045260245ffdfea264697066735822122082a1aebb6c6ad13b2c7af56c970465c4a67cf171cc2d2514a188ed9526c0e6bc64736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/EnumerableMap.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/EnumerableMap.json new file mode 100644 index 00000000..aa528f0e --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/EnumerableMap.json @@ -0,0 +1,33 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "EnumerableMap", + "sourceName": "contracts/utils/structs/EnumerableMap.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "bytes", + "name": "key", + "type": "bytes" + } + ], + "name": "EnumerableMapNonexistentBytesKey", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "key", + "type": "bytes32" + } + ], + "name": "EnumerableMapNonexistentKey", + "type": "error" + } + ], + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220b53ceded6a25e67b8a78704b61dbe0db2708e1c58ff3b6b36fb019a115fce18264736f6c634300081b0033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220b53ceded6a25e67b8a78704b61dbe0db2708e1c58ff3b6b36fb019a115fce18264736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/EnumerableSet.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/EnumerableSet.json new file mode 100644 index 00000000..79b01cf1 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/EnumerableSet.json @@ -0,0 +1,10 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "EnumerableSet", + "sourceName": "contracts/utils/structs/EnumerableSet.sol", + "abi": [], + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212205eacf73835e79b1e77d9e2f496f665141d03c9acb4be23de87fb532638e1baff64736f6c634300081b0033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212205eacf73835e79b1e77d9e2f496f665141d03c9acb4be23de87fb532638e1baff64736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Errors.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Errors.json new file mode 100644 index 00000000..01567b47 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Errors.json @@ -0,0 +1,48 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "Errors", + "sourceName": "contracts/utils/Errors.sol", + "abi": [ + { + "inputs": [], + "name": "FailedCall", + "type": "error" + }, + { + "inputs": [], + "name": "FailedDeployment", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + } + ], + "name": "InsufficientBalance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "MissingPrecompile", + "type": "error" + } + ], + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212203674537990f67e9f6c04733daf526fbb00a8b67fab7890e388d422b34bcefe7e64736f6c634300081b0033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212203674537990f67e9f6c04733daf526fbb00a8b67fab7890e388d422b34bcefe7e64736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Governor.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Governor.json new file mode 100644 index 00000000..0925fc70 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Governor.json @@ -0,0 +1,1372 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "Governor", + "sourceName": "contracts/governance/Governor.sol", + "abi": [ + { + "inputs": [], + "name": "FailedCall", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "voter", + "type": "address" + } + ], + "name": "GovernorAlreadyCastVote", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorAlreadyQueuedProposal", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorDisabledDeposit", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "proposer", + "type": "address" + }, + { + "internalType": "uint256", + "name": "votes", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "threshold", + "type": "uint256" + } + ], + "name": "GovernorInsufficientProposerVotes", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "targets", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "calldatas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "values", + "type": "uint256" + } + ], + "name": "GovernorInvalidProposalLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "voter", + "type": "address" + } + ], + "name": "GovernorInvalidSignature", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorInvalidVoteParams", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorInvalidVoteType", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "votingPeriod", + "type": "uint256" + } + ], + "name": "GovernorInvalidVotingPeriod", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorNonexistentProposal", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorNotQueuedProposal", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "GovernorOnlyExecutor", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorQueueNotImplemented", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "proposer", + "type": "address" + } + ], + "name": "GovernorRestrictedProposer", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "GovernorUnableToCancel", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "enum IGovernor.ProposalState", + "name": "current", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "expectedStates", + "type": "bytes32" + } + ], + "name": "GovernorUnexpectedProposalState", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "currentNonce", + "type": "uint256" + } + ], + "name": "InvalidAccountNonce", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidShortString", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "bits", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "SafeCastOverflowedUintDowncast", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "str", + "type": "string" + } + ], + "name": "StringTooLong", + "type": "error" + }, + { + "anonymous": false, + "inputs": [], + "name": "EIP712DomainChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "ProposalCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "proposer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "string[]", + "name": "signatures", + "type": "string[]" + }, + { + "indexed": false, + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "voteStart", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "voteEnd", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "name": "ProposalCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "ProposalExecuted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "etaSeconds", + "type": "uint256" + } + ], + "name": "ProposalQueued", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "weight", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "VoteCast", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "weight", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "VoteCastWithParams", + "type": "event" + }, + { + "inputs": [], + "name": "BALLOT_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CLOCK_MODE", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "COUNTING_MODE", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "EXTENDED_BALLOT_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "cancel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + } + ], + "name": "castVote", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "castVoteBySig", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "castVoteWithReason", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "castVoteWithReasonAndParams", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "castVoteWithReasonAndParamsBySig", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "clock", + "outputs": [ + { + "internalType": "uint48", + "name": "", + "type": "uint48" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "eip712Domain", + "outputs": [ + { + "internalType": "bytes1", + "name": "fields", + "type": "bytes1" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "version", + "type": "string" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "verifyingContract", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + }, + { + "internalType": "uint256[]", + "name": "extensions", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "execute", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "getProposalId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + } + ], + "name": "getVotes", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "getVotesWithParams", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasVoted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "hashProposal", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC1155BatchReceived", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC1155Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC721Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalDeadline", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalEta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "proposalNeedsQueuing", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalProposer", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proposalThreshold", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "name": "propose", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "queue", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + } + ], + "name": "quorum", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "relay", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "state", + "outputs": [ + { + "internalType": "enum IGovernor.ProposalState", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "votingDelay", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "votingPeriod", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/GovernorCountingFractional.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/GovernorCountingFractional.json new file mode 100644 index 00000000..b1f0de3a --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/GovernorCountingFractional.json @@ -0,0 +1,1446 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "GovernorCountingFractional", + "sourceName": "contracts/governance/extensions/GovernorCountingFractional.sol", + "abi": [ + { + "inputs": [], + "name": "FailedCall", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "voter", + "type": "address" + } + ], + "name": "GovernorAlreadyCastVote", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorAlreadyQueuedProposal", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorDisabledDeposit", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "internalType": "uint256", + "name": "usedVotes", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "remainingWeight", + "type": "uint256" + } + ], + "name": "GovernorExceedRemainingWeight", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "proposer", + "type": "address" + }, + { + "internalType": "uint256", + "name": "votes", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "threshold", + "type": "uint256" + } + ], + "name": "GovernorInsufficientProposerVotes", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "targets", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "calldatas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "values", + "type": "uint256" + } + ], + "name": "GovernorInvalidProposalLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "voter", + "type": "address" + } + ], + "name": "GovernorInvalidSignature", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorInvalidVoteParams", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorInvalidVoteType", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "votingPeriod", + "type": "uint256" + } + ], + "name": "GovernorInvalidVotingPeriod", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorNonexistentProposal", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorNotQueuedProposal", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "GovernorOnlyExecutor", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorQueueNotImplemented", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "proposer", + "type": "address" + } + ], + "name": "GovernorRestrictedProposer", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "GovernorUnableToCancel", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "enum IGovernor.ProposalState", + "name": "current", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "expectedStates", + "type": "bytes32" + } + ], + "name": "GovernorUnexpectedProposalState", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "currentNonce", + "type": "uint256" + } + ], + "name": "InvalidAccountNonce", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidShortString", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "bits", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "SafeCastOverflowedUintDowncast", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "str", + "type": "string" + } + ], + "name": "StringTooLong", + "type": "error" + }, + { + "anonymous": false, + "inputs": [], + "name": "EIP712DomainChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "ProposalCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "proposer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "string[]", + "name": "signatures", + "type": "string[]" + }, + { + "indexed": false, + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "voteStart", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "voteEnd", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "name": "ProposalCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "ProposalExecuted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "etaSeconds", + "type": "uint256" + } + ], + "name": "ProposalQueued", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "weight", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "VoteCast", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "weight", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "VoteCastWithParams", + "type": "event" + }, + { + "inputs": [], + "name": "BALLOT_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CLOCK_MODE", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "COUNTING_MODE", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "EXTENDED_BALLOT_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "cancel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + } + ], + "name": "castVote", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "castVoteBySig", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "castVoteWithReason", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "castVoteWithReasonAndParams", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "castVoteWithReasonAndParamsBySig", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "clock", + "outputs": [ + { + "internalType": "uint48", + "name": "", + "type": "uint48" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "eip712Domain", + "outputs": [ + { + "internalType": "bytes1", + "name": "fields", + "type": "bytes1" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "version", + "type": "string" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "verifyingContract", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + }, + { + "internalType": "uint256[]", + "name": "extensions", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "execute", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "getProposalId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + } + ], + "name": "getVotes", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "getVotesWithParams", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasVoted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "hashProposal", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC1155BatchReceived", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC1155Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC721Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalDeadline", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalEta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "proposalNeedsQueuing", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalProposer", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proposalThreshold", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalVotes", + "outputs": [ + { + "internalType": "uint256", + "name": "againstVotes", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "forVotes", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "abstainVotes", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "name": "propose", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "queue", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + } + ], + "name": "quorum", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "relay", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "state", + "outputs": [ + { + "internalType": "enum IGovernor.ProposalState", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "usedVotes", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "votingDelay", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "votingPeriod", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/GovernorCountingOverridable.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/GovernorCountingOverridable.json new file mode 100644 index 00000000..56c0e83a --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/GovernorCountingOverridable.json @@ -0,0 +1,1598 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "GovernorCountingOverridable", + "sourceName": "contracts/governance/extensions/GovernorCountingOverridable.sol", + "abi": [ + { + "inputs": [], + "name": "FailedCall", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "voter", + "type": "address" + } + ], + "name": "GovernorAlreadyCastVote", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "GovernorAlreadyOverriddenVote", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorAlreadyQueuedProposal", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorDisabledDeposit", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "proposer", + "type": "address" + }, + { + "internalType": "uint256", + "name": "votes", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "threshold", + "type": "uint256" + } + ], + "name": "GovernorInsufficientProposerVotes", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "targets", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "calldatas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "values", + "type": "uint256" + } + ], + "name": "GovernorInvalidProposalLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "voter", + "type": "address" + } + ], + "name": "GovernorInvalidSignature", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorInvalidVoteParams", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorInvalidVoteType", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "votingPeriod", + "type": "uint256" + } + ], + "name": "GovernorInvalidVotingPeriod", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorNonexistentProposal", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorNotQueuedProposal", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "GovernorOnlyExecutor", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorQueueNotImplemented", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "proposer", + "type": "address" + } + ], + "name": "GovernorRestrictedProposer", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "GovernorUnableToCancel", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "enum IGovernor.ProposalState", + "name": "current", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "expectedStates", + "type": "bytes32" + } + ], + "name": "GovernorUnexpectedProposalState", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "currentNonce", + "type": "uint256" + } + ], + "name": "InvalidAccountNonce", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidShortString", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "bits", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "SafeCastOverflowedUintDowncast", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "str", + "type": "string" + } + ], + "name": "StringTooLong", + "type": "error" + }, + { + "anonymous": false, + "inputs": [], + "name": "EIP712DomainChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "weight", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "OverrideVoteCast", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "ProposalCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "proposer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "string[]", + "name": "signatures", + "type": "string[]" + }, + { + "indexed": false, + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "voteStart", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "voteEnd", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "name": "ProposalCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "ProposalExecuted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "etaSeconds", + "type": "uint256" + } + ], + "name": "ProposalQueued", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "weight", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "VoteCast", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "weight", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "VoteCastWithParams", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "delegate", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "weight", + "type": "uint256" + } + ], + "name": "VoteReduced", + "type": "event" + }, + { + "inputs": [], + "name": "BALLOT_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CLOCK_MODE", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "COUNTING_MODE", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "EXTENDED_BALLOT_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "OVERRIDE_BALLOT_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "cancel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "castOverrideVote", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "castOverrideVoteBySig", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + } + ], + "name": "castVote", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "castVoteBySig", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "castVoteWithReason", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "castVoteWithReasonAndParams", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "castVoteWithReasonAndParamsBySig", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "clock", + "outputs": [ + { + "internalType": "uint48", + "name": "", + "type": "uint48" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "eip712Domain", + "outputs": [ + { + "internalType": "bytes1", + "name": "fields", + "type": "bytes1" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "version", + "type": "string" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "verifyingContract", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + }, + { + "internalType": "uint256[]", + "name": "extensions", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "execute", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "getProposalId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + } + ], + "name": "getVotes", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "getVotesWithParams", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasVoted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasVotedOverride", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "hashProposal", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC1155BatchReceived", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC1155Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC721Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalDeadline", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalEta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "proposalNeedsQueuing", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalProposer", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proposalThreshold", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalVotes", + "outputs": [ + { + "internalType": "uint256", + "name": "againstVotes", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "forVotes", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "abstainVotes", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "name": "propose", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "queue", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + } + ], + "name": "quorum", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "relay", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "state", + "outputs": [ + { + "internalType": "enum IGovernor.ProposalState", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "token", + "outputs": [ + { + "internalType": "contract IERC5805", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "votingDelay", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "votingPeriod", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/GovernorCountingSimple.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/GovernorCountingSimple.json new file mode 100644 index 00000000..f5c5c2fe --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/GovernorCountingSimple.json @@ -0,0 +1,1401 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "GovernorCountingSimple", + "sourceName": "contracts/governance/extensions/GovernorCountingSimple.sol", + "abi": [ + { + "inputs": [], + "name": "FailedCall", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "voter", + "type": "address" + } + ], + "name": "GovernorAlreadyCastVote", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorAlreadyQueuedProposal", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorDisabledDeposit", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "proposer", + "type": "address" + }, + { + "internalType": "uint256", + "name": "votes", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "threshold", + "type": "uint256" + } + ], + "name": "GovernorInsufficientProposerVotes", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "targets", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "calldatas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "values", + "type": "uint256" + } + ], + "name": "GovernorInvalidProposalLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "voter", + "type": "address" + } + ], + "name": "GovernorInvalidSignature", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorInvalidVoteParams", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorInvalidVoteType", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "votingPeriod", + "type": "uint256" + } + ], + "name": "GovernorInvalidVotingPeriod", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorNonexistentProposal", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorNotQueuedProposal", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "GovernorOnlyExecutor", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorQueueNotImplemented", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "proposer", + "type": "address" + } + ], + "name": "GovernorRestrictedProposer", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "GovernorUnableToCancel", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "enum IGovernor.ProposalState", + "name": "current", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "expectedStates", + "type": "bytes32" + } + ], + "name": "GovernorUnexpectedProposalState", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "currentNonce", + "type": "uint256" + } + ], + "name": "InvalidAccountNonce", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidShortString", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "bits", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "SafeCastOverflowedUintDowncast", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "str", + "type": "string" + } + ], + "name": "StringTooLong", + "type": "error" + }, + { + "anonymous": false, + "inputs": [], + "name": "EIP712DomainChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "ProposalCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "proposer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "string[]", + "name": "signatures", + "type": "string[]" + }, + { + "indexed": false, + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "voteStart", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "voteEnd", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "name": "ProposalCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "ProposalExecuted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "etaSeconds", + "type": "uint256" + } + ], + "name": "ProposalQueued", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "weight", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "VoteCast", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "weight", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "VoteCastWithParams", + "type": "event" + }, + { + "inputs": [], + "name": "BALLOT_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CLOCK_MODE", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "COUNTING_MODE", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "EXTENDED_BALLOT_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "cancel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + } + ], + "name": "castVote", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "castVoteBySig", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "castVoteWithReason", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "castVoteWithReasonAndParams", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "castVoteWithReasonAndParamsBySig", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "clock", + "outputs": [ + { + "internalType": "uint48", + "name": "", + "type": "uint48" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "eip712Domain", + "outputs": [ + { + "internalType": "bytes1", + "name": "fields", + "type": "bytes1" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "version", + "type": "string" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "verifyingContract", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + }, + { + "internalType": "uint256[]", + "name": "extensions", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "execute", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "getProposalId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + } + ], + "name": "getVotes", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "getVotesWithParams", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasVoted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "hashProposal", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC1155BatchReceived", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC1155Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC721Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalDeadline", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalEta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "proposalNeedsQueuing", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalProposer", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proposalThreshold", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalVotes", + "outputs": [ + { + "internalType": "uint256", + "name": "againstVotes", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "forVotes", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "abstainVotes", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "name": "propose", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "queue", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + } + ], + "name": "quorum", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "relay", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "state", + "outputs": [ + { + "internalType": "enum IGovernor.ProposalState", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "votingDelay", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "votingPeriod", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/GovernorNoncesKeyed.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/GovernorNoncesKeyed.json new file mode 100644 index 00000000..82ca96e9 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/GovernorNoncesKeyed.json @@ -0,0 +1,1396 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "GovernorNoncesKeyed", + "sourceName": "contracts/governance/extensions/GovernorNoncesKeyed.sol", + "abi": [ + { + "inputs": [], + "name": "FailedCall", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "voter", + "type": "address" + } + ], + "name": "GovernorAlreadyCastVote", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorAlreadyQueuedProposal", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorDisabledDeposit", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "proposer", + "type": "address" + }, + { + "internalType": "uint256", + "name": "votes", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "threshold", + "type": "uint256" + } + ], + "name": "GovernorInsufficientProposerVotes", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "targets", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "calldatas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "values", + "type": "uint256" + } + ], + "name": "GovernorInvalidProposalLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "voter", + "type": "address" + } + ], + "name": "GovernorInvalidSignature", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorInvalidVoteParams", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorInvalidVoteType", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "votingPeriod", + "type": "uint256" + } + ], + "name": "GovernorInvalidVotingPeriod", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorNonexistentProposal", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorNotQueuedProposal", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "GovernorOnlyExecutor", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorQueueNotImplemented", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "proposer", + "type": "address" + } + ], + "name": "GovernorRestrictedProposer", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "GovernorUnableToCancel", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "enum IGovernor.ProposalState", + "name": "current", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "expectedStates", + "type": "bytes32" + } + ], + "name": "GovernorUnexpectedProposalState", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "currentNonce", + "type": "uint256" + } + ], + "name": "InvalidAccountNonce", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidShortString", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "bits", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "SafeCastOverflowedUintDowncast", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "str", + "type": "string" + } + ], + "name": "StringTooLong", + "type": "error" + }, + { + "anonymous": false, + "inputs": [], + "name": "EIP712DomainChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "ProposalCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "proposer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "string[]", + "name": "signatures", + "type": "string[]" + }, + { + "indexed": false, + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "voteStart", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "voteEnd", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "name": "ProposalCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "ProposalExecuted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "etaSeconds", + "type": "uint256" + } + ], + "name": "ProposalQueued", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "weight", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "VoteCast", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "weight", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "VoteCastWithParams", + "type": "event" + }, + { + "inputs": [], + "name": "BALLOT_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CLOCK_MODE", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "COUNTING_MODE", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "EXTENDED_BALLOT_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "cancel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + } + ], + "name": "castVote", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "castVoteBySig", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "castVoteWithReason", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "castVoteWithReasonAndParams", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "castVoteWithReasonAndParamsBySig", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "clock", + "outputs": [ + { + "internalType": "uint48", + "name": "", + "type": "uint48" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "eip712Domain", + "outputs": [ + { + "internalType": "bytes1", + "name": "fields", + "type": "bytes1" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "version", + "type": "string" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "verifyingContract", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + }, + { + "internalType": "uint256[]", + "name": "extensions", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "execute", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "getProposalId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + } + ], + "name": "getVotes", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "getVotesWithParams", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasVoted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "hashProposal", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint192", + "name": "key", + "type": "uint192" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC1155BatchReceived", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC1155Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC721Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalDeadline", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalEta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "proposalNeedsQueuing", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalProposer", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proposalThreshold", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "name": "propose", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "queue", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + } + ], + "name": "quorum", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "relay", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "state", + "outputs": [ + { + "internalType": "enum IGovernor.ProposalState", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "votingDelay", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "votingPeriod", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/GovernorPreventLateQuorum.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/GovernorPreventLateQuorum.json new file mode 100644 index 00000000..1cbb4fd1 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/GovernorPreventLateQuorum.json @@ -0,0 +1,1436 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "GovernorPreventLateQuorum", + "sourceName": "contracts/governance/extensions/GovernorPreventLateQuorum.sol", + "abi": [ + { + "inputs": [], + "name": "FailedCall", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "voter", + "type": "address" + } + ], + "name": "GovernorAlreadyCastVote", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorAlreadyQueuedProposal", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorDisabledDeposit", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "proposer", + "type": "address" + }, + { + "internalType": "uint256", + "name": "votes", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "threshold", + "type": "uint256" + } + ], + "name": "GovernorInsufficientProposerVotes", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "targets", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "calldatas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "values", + "type": "uint256" + } + ], + "name": "GovernorInvalidProposalLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "voter", + "type": "address" + } + ], + "name": "GovernorInvalidSignature", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorInvalidVoteParams", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorInvalidVoteType", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "votingPeriod", + "type": "uint256" + } + ], + "name": "GovernorInvalidVotingPeriod", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorNonexistentProposal", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorNotQueuedProposal", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "GovernorOnlyExecutor", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorQueueNotImplemented", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "proposer", + "type": "address" + } + ], + "name": "GovernorRestrictedProposer", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "GovernorUnableToCancel", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "enum IGovernor.ProposalState", + "name": "current", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "expectedStates", + "type": "bytes32" + } + ], + "name": "GovernorUnexpectedProposalState", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "currentNonce", + "type": "uint256" + } + ], + "name": "InvalidAccountNonce", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidShortString", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "bits", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "SafeCastOverflowedUintDowncast", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "str", + "type": "string" + } + ], + "name": "StringTooLong", + "type": "error" + }, + { + "anonymous": false, + "inputs": [], + "name": "EIP712DomainChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "oldVoteExtension", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "newVoteExtension", + "type": "uint64" + } + ], + "name": "LateQuorumVoteExtensionSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "ProposalCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "proposer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "string[]", + "name": "signatures", + "type": "string[]" + }, + { + "indexed": false, + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "voteStart", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "voteEnd", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "name": "ProposalCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "ProposalExecuted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "extendedDeadline", + "type": "uint64" + } + ], + "name": "ProposalExtended", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "etaSeconds", + "type": "uint256" + } + ], + "name": "ProposalQueued", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "weight", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "VoteCast", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "weight", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "VoteCastWithParams", + "type": "event" + }, + { + "inputs": [], + "name": "BALLOT_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CLOCK_MODE", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "COUNTING_MODE", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "EXTENDED_BALLOT_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "cancel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + } + ], + "name": "castVote", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "castVoteBySig", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "castVoteWithReason", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "castVoteWithReasonAndParams", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "castVoteWithReasonAndParamsBySig", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "clock", + "outputs": [ + { + "internalType": "uint48", + "name": "", + "type": "uint48" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "eip712Domain", + "outputs": [ + { + "internalType": "bytes1", + "name": "fields", + "type": "bytes1" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "version", + "type": "string" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "verifyingContract", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + }, + { + "internalType": "uint256[]", + "name": "extensions", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "execute", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "getProposalId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + } + ], + "name": "getVotes", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "getVotesWithParams", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasVoted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "hashProposal", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "lateQuorumVoteExtension", + "outputs": [ + { + "internalType": "uint48", + "name": "", + "type": "uint48" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC1155BatchReceived", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC1155Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC721Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalDeadline", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalEta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "proposalNeedsQueuing", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalProposer", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proposalThreshold", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "name": "propose", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "queue", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + } + ], + "name": "quorum", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "relay", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint48", + "name": "newVoteExtension", + "type": "uint48" + } + ], + "name": "setLateQuorumVoteExtension", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "state", + "outputs": [ + { + "internalType": "enum IGovernor.ProposalState", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "votingDelay", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "votingPeriod", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/GovernorProposalGuardian.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/GovernorProposalGuardian.json new file mode 100644 index 00000000..153b1e05 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/GovernorProposalGuardian.json @@ -0,0 +1,1417 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "GovernorProposalGuardian", + "sourceName": "contracts/governance/extensions/GovernorProposalGuardian.sol", + "abi": [ + { + "inputs": [], + "name": "FailedCall", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "voter", + "type": "address" + } + ], + "name": "GovernorAlreadyCastVote", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorAlreadyQueuedProposal", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorDisabledDeposit", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "proposer", + "type": "address" + }, + { + "internalType": "uint256", + "name": "votes", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "threshold", + "type": "uint256" + } + ], + "name": "GovernorInsufficientProposerVotes", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "targets", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "calldatas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "values", + "type": "uint256" + } + ], + "name": "GovernorInvalidProposalLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "voter", + "type": "address" + } + ], + "name": "GovernorInvalidSignature", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorInvalidVoteParams", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorInvalidVoteType", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "votingPeriod", + "type": "uint256" + } + ], + "name": "GovernorInvalidVotingPeriod", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorNonexistentProposal", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorNotQueuedProposal", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "GovernorOnlyExecutor", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorQueueNotImplemented", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "proposer", + "type": "address" + } + ], + "name": "GovernorRestrictedProposer", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "GovernorUnableToCancel", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "enum IGovernor.ProposalState", + "name": "current", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "expectedStates", + "type": "bytes32" + } + ], + "name": "GovernorUnexpectedProposalState", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "currentNonce", + "type": "uint256" + } + ], + "name": "InvalidAccountNonce", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidShortString", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "bits", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "SafeCastOverflowedUintDowncast", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "str", + "type": "string" + } + ], + "name": "StringTooLong", + "type": "error" + }, + { + "anonymous": false, + "inputs": [], + "name": "EIP712DomainChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "ProposalCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "proposer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "string[]", + "name": "signatures", + "type": "string[]" + }, + { + "indexed": false, + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "voteStart", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "voteEnd", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "name": "ProposalCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "ProposalExecuted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldProposalGuardian", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newProposalGuardian", + "type": "address" + } + ], + "name": "ProposalGuardianSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "etaSeconds", + "type": "uint256" + } + ], + "name": "ProposalQueued", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "weight", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "VoteCast", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "weight", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "VoteCastWithParams", + "type": "event" + }, + { + "inputs": [], + "name": "BALLOT_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CLOCK_MODE", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "COUNTING_MODE", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "EXTENDED_BALLOT_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "cancel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + } + ], + "name": "castVote", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "castVoteBySig", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "castVoteWithReason", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "castVoteWithReasonAndParams", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "castVoteWithReasonAndParamsBySig", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "clock", + "outputs": [ + { + "internalType": "uint48", + "name": "", + "type": "uint48" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "eip712Domain", + "outputs": [ + { + "internalType": "bytes1", + "name": "fields", + "type": "bytes1" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "version", + "type": "string" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "verifyingContract", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + }, + { + "internalType": "uint256[]", + "name": "extensions", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "execute", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "getProposalId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + } + ], + "name": "getVotes", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "getVotesWithParams", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasVoted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "hashProposal", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC1155BatchReceived", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC1155Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC721Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalDeadline", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalEta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proposalGuardian", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "proposalNeedsQueuing", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalProposer", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proposalThreshold", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "name": "propose", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "queue", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + } + ], + "name": "quorum", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "relay", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newProposalGuardian", + "type": "address" + } + ], + "name": "setProposalGuardian", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "state", + "outputs": [ + { + "internalType": "enum IGovernor.ProposalState", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "votingDelay", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "votingPeriod", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/GovernorSequentialProposalId.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/GovernorSequentialProposalId.json new file mode 100644 index 00000000..85ca25ab --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/GovernorSequentialProposalId.json @@ -0,0 +1,1390 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "GovernorSequentialProposalId", + "sourceName": "contracts/governance/extensions/GovernorSequentialProposalId.sol", + "abi": [ + { + "inputs": [], + "name": "FailedCall", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "voter", + "type": "address" + } + ], + "name": "GovernorAlreadyCastVote", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorAlreadyInitializedLatestProposalId", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorAlreadyQueuedProposal", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorDisabledDeposit", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "proposer", + "type": "address" + }, + { + "internalType": "uint256", + "name": "votes", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "threshold", + "type": "uint256" + } + ], + "name": "GovernorInsufficientProposerVotes", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "targets", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "calldatas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "values", + "type": "uint256" + } + ], + "name": "GovernorInvalidProposalLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "voter", + "type": "address" + } + ], + "name": "GovernorInvalidSignature", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorInvalidVoteParams", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorInvalidVoteType", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "votingPeriod", + "type": "uint256" + } + ], + "name": "GovernorInvalidVotingPeriod", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorNonexistentProposal", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorNotQueuedProposal", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "GovernorOnlyExecutor", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorQueueNotImplemented", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "proposer", + "type": "address" + } + ], + "name": "GovernorRestrictedProposer", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "GovernorUnableToCancel", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "enum IGovernor.ProposalState", + "name": "current", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "expectedStates", + "type": "bytes32" + } + ], + "name": "GovernorUnexpectedProposalState", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "currentNonce", + "type": "uint256" + } + ], + "name": "InvalidAccountNonce", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidShortString", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "bits", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "SafeCastOverflowedUintDowncast", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "str", + "type": "string" + } + ], + "name": "StringTooLong", + "type": "error" + }, + { + "anonymous": false, + "inputs": [], + "name": "EIP712DomainChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "ProposalCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "proposer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "string[]", + "name": "signatures", + "type": "string[]" + }, + { + "indexed": false, + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "voteStart", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "voteEnd", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "name": "ProposalCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "ProposalExecuted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "etaSeconds", + "type": "uint256" + } + ], + "name": "ProposalQueued", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "weight", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "VoteCast", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "weight", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "VoteCastWithParams", + "type": "event" + }, + { + "inputs": [], + "name": "BALLOT_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CLOCK_MODE", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "COUNTING_MODE", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "EXTENDED_BALLOT_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "cancel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + } + ], + "name": "castVote", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "castVoteBySig", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "castVoteWithReason", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "castVoteWithReasonAndParams", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "castVoteWithReasonAndParamsBySig", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "clock", + "outputs": [ + { + "internalType": "uint48", + "name": "", + "type": "uint48" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "eip712Domain", + "outputs": [ + { + "internalType": "bytes1", + "name": "fields", + "type": "bytes1" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "version", + "type": "string" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "verifyingContract", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + }, + { + "internalType": "uint256[]", + "name": "extensions", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "execute", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "getProposalId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + } + ], + "name": "getVotes", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "getVotesWithParams", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasVoted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "hashProposal", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "latestProposalId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC1155BatchReceived", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC1155Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC721Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalDeadline", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalEta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "proposalNeedsQueuing", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalProposer", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proposalThreshold", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "name": "propose", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "queue", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + } + ], + "name": "quorum", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "relay", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "state", + "outputs": [ + { + "internalType": "enum IGovernor.ProposalState", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "votingDelay", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "votingPeriod", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/GovernorSettings.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/GovernorSettings.json new file mode 100644 index 00000000..9c5068b2 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/GovernorSettings.json @@ -0,0 +1,1468 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "GovernorSettings", + "sourceName": "contracts/governance/extensions/GovernorSettings.sol", + "abi": [ + { + "inputs": [], + "name": "FailedCall", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "voter", + "type": "address" + } + ], + "name": "GovernorAlreadyCastVote", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorAlreadyQueuedProposal", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorDisabledDeposit", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "proposer", + "type": "address" + }, + { + "internalType": "uint256", + "name": "votes", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "threshold", + "type": "uint256" + } + ], + "name": "GovernorInsufficientProposerVotes", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "targets", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "calldatas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "values", + "type": "uint256" + } + ], + "name": "GovernorInvalidProposalLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "voter", + "type": "address" + } + ], + "name": "GovernorInvalidSignature", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorInvalidVoteParams", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorInvalidVoteType", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "votingPeriod", + "type": "uint256" + } + ], + "name": "GovernorInvalidVotingPeriod", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorNonexistentProposal", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorNotQueuedProposal", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "GovernorOnlyExecutor", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorQueueNotImplemented", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "proposer", + "type": "address" + } + ], + "name": "GovernorRestrictedProposer", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "GovernorUnableToCancel", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "enum IGovernor.ProposalState", + "name": "current", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "expectedStates", + "type": "bytes32" + } + ], + "name": "GovernorUnexpectedProposalState", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "currentNonce", + "type": "uint256" + } + ], + "name": "InvalidAccountNonce", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidShortString", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "bits", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "SafeCastOverflowedUintDowncast", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "str", + "type": "string" + } + ], + "name": "StringTooLong", + "type": "error" + }, + { + "anonymous": false, + "inputs": [], + "name": "EIP712DomainChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "ProposalCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "proposer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "string[]", + "name": "signatures", + "type": "string[]" + }, + { + "indexed": false, + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "voteStart", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "voteEnd", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "name": "ProposalCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "ProposalExecuted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "etaSeconds", + "type": "uint256" + } + ], + "name": "ProposalQueued", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldProposalThreshold", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newProposalThreshold", + "type": "uint256" + } + ], + "name": "ProposalThresholdSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "weight", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "VoteCast", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "weight", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "VoteCastWithParams", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldVotingDelay", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newVotingDelay", + "type": "uint256" + } + ], + "name": "VotingDelaySet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldVotingPeriod", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newVotingPeriod", + "type": "uint256" + } + ], + "name": "VotingPeriodSet", + "type": "event" + }, + { + "inputs": [], + "name": "BALLOT_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CLOCK_MODE", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "COUNTING_MODE", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "EXTENDED_BALLOT_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "cancel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + } + ], + "name": "castVote", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "castVoteBySig", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "castVoteWithReason", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "castVoteWithReasonAndParams", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "castVoteWithReasonAndParamsBySig", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "clock", + "outputs": [ + { + "internalType": "uint48", + "name": "", + "type": "uint48" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "eip712Domain", + "outputs": [ + { + "internalType": "bytes1", + "name": "fields", + "type": "bytes1" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "version", + "type": "string" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "verifyingContract", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + }, + { + "internalType": "uint256[]", + "name": "extensions", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "execute", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "getProposalId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + } + ], + "name": "getVotes", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "getVotesWithParams", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasVoted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "hashProposal", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC1155BatchReceived", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC1155Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC721Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalDeadline", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalEta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "proposalNeedsQueuing", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalProposer", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proposalThreshold", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "name": "propose", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "queue", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + } + ], + "name": "quorum", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "relay", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newProposalThreshold", + "type": "uint256" + } + ], + "name": "setProposalThreshold", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint48", + "name": "newVotingDelay", + "type": "uint48" + } + ], + "name": "setVotingDelay", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "newVotingPeriod", + "type": "uint32" + } + ], + "name": "setVotingPeriod", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "state", + "outputs": [ + { + "internalType": "enum IGovernor.ProposalState", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "votingDelay", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "votingPeriod", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/GovernorStorage.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/GovernorStorage.json new file mode 100644 index 00000000..2c229dd0 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/GovernorStorage.json @@ -0,0 +1,1497 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "GovernorStorage", + "sourceName": "contracts/governance/extensions/GovernorStorage.sol", + "abi": [ + { + "inputs": [], + "name": "FailedCall", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "voter", + "type": "address" + } + ], + "name": "GovernorAlreadyCastVote", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorAlreadyQueuedProposal", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorDisabledDeposit", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "proposer", + "type": "address" + }, + { + "internalType": "uint256", + "name": "votes", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "threshold", + "type": "uint256" + } + ], + "name": "GovernorInsufficientProposerVotes", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "targets", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "calldatas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "values", + "type": "uint256" + } + ], + "name": "GovernorInvalidProposalLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "voter", + "type": "address" + } + ], + "name": "GovernorInvalidSignature", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorInvalidVoteParams", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorInvalidVoteType", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "votingPeriod", + "type": "uint256" + } + ], + "name": "GovernorInvalidVotingPeriod", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorNonexistentProposal", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorNotQueuedProposal", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "GovernorOnlyExecutor", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorQueueNotImplemented", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "proposer", + "type": "address" + } + ], + "name": "GovernorRestrictedProposer", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "GovernorUnableToCancel", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "enum IGovernor.ProposalState", + "name": "current", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "expectedStates", + "type": "bytes32" + } + ], + "name": "GovernorUnexpectedProposalState", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "currentNonce", + "type": "uint256" + } + ], + "name": "InvalidAccountNonce", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidShortString", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "bits", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "SafeCastOverflowedUintDowncast", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "str", + "type": "string" + } + ], + "name": "StringTooLong", + "type": "error" + }, + { + "anonymous": false, + "inputs": [], + "name": "EIP712DomainChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "ProposalCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "proposer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "string[]", + "name": "signatures", + "type": "string[]" + }, + { + "indexed": false, + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "voteStart", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "voteEnd", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "name": "ProposalCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "ProposalExecuted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "etaSeconds", + "type": "uint256" + } + ], + "name": "ProposalQueued", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "weight", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "VoteCast", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "weight", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "VoteCastWithParams", + "type": "event" + }, + { + "inputs": [], + "name": "BALLOT_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CLOCK_MODE", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "COUNTING_MODE", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "EXTENDED_BALLOT_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "cancel", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "cancel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + } + ], + "name": "castVote", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "castVoteBySig", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "castVoteWithReason", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "castVoteWithReasonAndParams", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "castVoteWithReasonAndParamsBySig", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "clock", + "outputs": [ + { + "internalType": "uint48", + "name": "", + "type": "uint48" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "eip712Domain", + "outputs": [ + { + "internalType": "bytes1", + "name": "fields", + "type": "bytes1" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "version", + "type": "string" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "verifyingContract", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + }, + { + "internalType": "uint256[]", + "name": "extensions", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "execute", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "execute", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "getProposalId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + } + ], + "name": "getVotes", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "getVotesWithParams", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasVoted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "hashProposal", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC1155BatchReceived", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC1155Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC721Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "proposalCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalDeadline", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalDetails", + "outputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "proposalDetailsAt", + "outputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalEta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "proposalNeedsQueuing", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalProposer", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proposalThreshold", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "name": "propose", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "queue", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "queue", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + } + ], + "name": "quorum", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "relay", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "state", + "outputs": [ + { + "internalType": "enum IGovernor.ProposalState", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "votingDelay", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "votingPeriod", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/GovernorSuperQuorum.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/GovernorSuperQuorum.json new file mode 100644 index 00000000..dfa180b8 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/GovernorSuperQuorum.json @@ -0,0 +1,1420 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "GovernorSuperQuorum", + "sourceName": "contracts/governance/extensions/GovernorSuperQuorum.sol", + "abi": [ + { + "inputs": [], + "name": "FailedCall", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "voter", + "type": "address" + } + ], + "name": "GovernorAlreadyCastVote", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorAlreadyQueuedProposal", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorDisabledDeposit", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "proposer", + "type": "address" + }, + { + "internalType": "uint256", + "name": "votes", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "threshold", + "type": "uint256" + } + ], + "name": "GovernorInsufficientProposerVotes", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "targets", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "calldatas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "values", + "type": "uint256" + } + ], + "name": "GovernorInvalidProposalLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "voter", + "type": "address" + } + ], + "name": "GovernorInvalidSignature", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorInvalidVoteParams", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorInvalidVoteType", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "votingPeriod", + "type": "uint256" + } + ], + "name": "GovernorInvalidVotingPeriod", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorNonexistentProposal", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorNotQueuedProposal", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "GovernorOnlyExecutor", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorQueueNotImplemented", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "proposer", + "type": "address" + } + ], + "name": "GovernorRestrictedProposer", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "GovernorUnableToCancel", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "enum IGovernor.ProposalState", + "name": "current", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "expectedStates", + "type": "bytes32" + } + ], + "name": "GovernorUnexpectedProposalState", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "currentNonce", + "type": "uint256" + } + ], + "name": "InvalidAccountNonce", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidShortString", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "bits", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "SafeCastOverflowedUintDowncast", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "str", + "type": "string" + } + ], + "name": "StringTooLong", + "type": "error" + }, + { + "anonymous": false, + "inputs": [], + "name": "EIP712DomainChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "ProposalCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "proposer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "string[]", + "name": "signatures", + "type": "string[]" + }, + { + "indexed": false, + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "voteStart", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "voteEnd", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "name": "ProposalCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "ProposalExecuted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "etaSeconds", + "type": "uint256" + } + ], + "name": "ProposalQueued", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "weight", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "VoteCast", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "weight", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "VoteCastWithParams", + "type": "event" + }, + { + "inputs": [], + "name": "BALLOT_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CLOCK_MODE", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "COUNTING_MODE", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "EXTENDED_BALLOT_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "cancel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + } + ], + "name": "castVote", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "castVoteBySig", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "castVoteWithReason", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "castVoteWithReasonAndParams", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "castVoteWithReasonAndParamsBySig", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "clock", + "outputs": [ + { + "internalType": "uint48", + "name": "", + "type": "uint48" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "eip712Domain", + "outputs": [ + { + "internalType": "bytes1", + "name": "fields", + "type": "bytes1" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "version", + "type": "string" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "verifyingContract", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + }, + { + "internalType": "uint256[]", + "name": "extensions", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "execute", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "getProposalId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + } + ], + "name": "getVotes", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "getVotesWithParams", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasVoted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "hashProposal", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC1155BatchReceived", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC1155Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC721Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalDeadline", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalEta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "proposalNeedsQueuing", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalProposer", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proposalThreshold", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalVotes", + "outputs": [ + { + "internalType": "uint256", + "name": "againstVotes", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "forVotes", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "abstainVotes", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "name": "propose", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "queue", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + } + ], + "name": "quorum", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "relay", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "state", + "outputs": [ + { + "internalType": "enum IGovernor.ProposalState", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + } + ], + "name": "superQuorum", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "votingDelay", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "votingPeriod", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/GovernorTimelockAccess.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/GovernorTimelockAccess.json new file mode 100644 index 00000000..a67165c9 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/GovernorTimelockAccess.json @@ -0,0 +1,1573 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "GovernorTimelockAccess", + "sourceName": "contracts/governance/extensions/GovernorTimelockAccess.sol", + "abi": [ + { + "inputs": [], + "name": "FailedCall", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "voter", + "type": "address" + } + ], + "name": "GovernorAlreadyCastVote", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorAlreadyQueuedProposal", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorDisabledDeposit", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "proposer", + "type": "address" + }, + { + "internalType": "uint256", + "name": "votes", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "threshold", + "type": "uint256" + } + ], + "name": "GovernorInsufficientProposerVotes", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "targets", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "calldatas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "values", + "type": "uint256" + } + ], + "name": "GovernorInvalidProposalLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "voter", + "type": "address" + } + ], + "name": "GovernorInvalidSignature", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorInvalidVoteParams", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorInvalidVoteType", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "votingPeriod", + "type": "uint256" + } + ], + "name": "GovernorInvalidVotingPeriod", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorLockedIgnore", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "expectedNonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "actualNonce", + "type": "uint256" + } + ], + "name": "GovernorMismatchedNonce", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorNonexistentProposal", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorNotQueuedProposal", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "GovernorOnlyExecutor", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorQueueNotImplemented", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "proposer", + "type": "address" + } + ], + "name": "GovernorRestrictedProposer", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "GovernorUnableToCancel", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "enum IGovernor.ProposalState", + "name": "current", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "expectedStates", + "type": "bytes32" + } + ], + "name": "GovernorUnexpectedProposalState", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "neededTimestamp", + "type": "uint256" + } + ], + "name": "GovernorUnmetDelay", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "currentNonce", + "type": "uint256" + } + ], + "name": "InvalidAccountNonce", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidShortString", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "bits", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "SafeCastOverflowedUintDowncast", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "str", + "type": "string" + } + ], + "name": "StringTooLong", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes4", + "name": "selector", + "type": "bytes4" + }, + { + "indexed": false, + "internalType": "bool", + "name": "ignored", + "type": "bool" + } + ], + "name": "AccessManagerIgnoredSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint32", + "name": "oldBaseDelaySeconds", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "newBaseDelaySeconds", + "type": "uint32" + } + ], + "name": "BaseDelaySet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "EIP712DomainChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "ProposalCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "proposer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "string[]", + "name": "signatures", + "type": "string[]" + }, + { + "indexed": false, + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "voteStart", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "voteEnd", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "name": "ProposalCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "ProposalExecuted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "etaSeconds", + "type": "uint256" + } + ], + "name": "ProposalQueued", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "weight", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "VoteCast", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "weight", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "VoteCastWithParams", + "type": "event" + }, + { + "inputs": [], + "name": "BALLOT_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CLOCK_MODE", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "COUNTING_MODE", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "EXTENDED_BALLOT_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "accessManager", + "outputs": [ + { + "internalType": "contract IAccessManager", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "baseDelaySeconds", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "cancel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + } + ], + "name": "castVote", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "castVoteBySig", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "castVoteWithReason", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "castVoteWithReasonAndParams", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "castVoteWithReasonAndParamsBySig", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "clock", + "outputs": [ + { + "internalType": "uint48", + "name": "", + "type": "uint48" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "eip712Domain", + "outputs": [ + { + "internalType": "bytes1", + "name": "fields", + "type": "bytes1" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "version", + "type": "string" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "verifyingContract", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + }, + { + "internalType": "uint256[]", + "name": "extensions", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "execute", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "getProposalId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + } + ], + "name": "getVotes", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "getVotesWithParams", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasVoted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "hashProposal", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes4", + "name": "selector", + "type": "bytes4" + } + ], + "name": "isAccessManagerIgnored", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC1155BatchReceived", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC1155Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC721Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalDeadline", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalEta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalExecutionPlan", + "outputs": [ + { + "internalType": "uint32", + "name": "delay", + "type": "uint32" + }, + { + "internalType": "bool[]", + "name": "indirect", + "type": "bool[]" + }, + { + "internalType": "bool[]", + "name": "withDelay", + "type": "bool[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalNeedsQueuing", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalProposer", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proposalThreshold", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "name": "propose", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "queue", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + } + ], + "name": "quorum", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "relay", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes4[]", + "name": "selectors", + "type": "bytes4[]" + }, + { + "internalType": "bool", + "name": "ignored", + "type": "bool" + } + ], + "name": "setAccessManagerIgnored", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "newBaseDelay", + "type": "uint32" + } + ], + "name": "setBaseDelaySeconds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "state", + "outputs": [ + { + "internalType": "enum IGovernor.ProposalState", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "votingDelay", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "votingPeriod", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/GovernorTimelockCompound.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/GovernorTimelockCompound.json new file mode 100644 index 00000000..01eb92ea --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/GovernorTimelockCompound.json @@ -0,0 +1,1440 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "GovernorTimelockCompound", + "sourceName": "contracts/governance/extensions/GovernorTimelockCompound.sol", + "abi": [ + { + "inputs": [], + "name": "FailedCall", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "voter", + "type": "address" + } + ], + "name": "GovernorAlreadyCastVote", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorAlreadyQueuedProposal", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorDisabledDeposit", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "proposer", + "type": "address" + }, + { + "internalType": "uint256", + "name": "votes", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "threshold", + "type": "uint256" + } + ], + "name": "GovernorInsufficientProposerVotes", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "targets", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "calldatas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "values", + "type": "uint256" + } + ], + "name": "GovernorInvalidProposalLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "voter", + "type": "address" + } + ], + "name": "GovernorInvalidSignature", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorInvalidVoteParams", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorInvalidVoteType", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "votingPeriod", + "type": "uint256" + } + ], + "name": "GovernorInvalidVotingPeriod", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorNonexistentProposal", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorNotQueuedProposal", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "GovernorOnlyExecutor", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorQueueNotImplemented", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "proposer", + "type": "address" + } + ], + "name": "GovernorRestrictedProposer", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "GovernorUnableToCancel", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "enum IGovernor.ProposalState", + "name": "current", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "expectedStates", + "type": "bytes32" + } + ], + "name": "GovernorUnexpectedProposalState", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + } + ], + "name": "InsufficientBalance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "currentNonce", + "type": "uint256" + } + ], + "name": "InvalidAccountNonce", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidShortString", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "bits", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "SafeCastOverflowedUintDowncast", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "str", + "type": "string" + } + ], + "name": "StringTooLong", + "type": "error" + }, + { + "anonymous": false, + "inputs": [], + "name": "EIP712DomainChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "ProposalCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "proposer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "string[]", + "name": "signatures", + "type": "string[]" + }, + { + "indexed": false, + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "voteStart", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "voteEnd", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "name": "ProposalCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "ProposalExecuted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "etaSeconds", + "type": "uint256" + } + ], + "name": "ProposalQueued", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldTimelock", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newTimelock", + "type": "address" + } + ], + "name": "TimelockChange", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "weight", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "VoteCast", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "weight", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "VoteCastWithParams", + "type": "event" + }, + { + "inputs": [], + "name": "BALLOT_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CLOCK_MODE", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "COUNTING_MODE", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "EXTENDED_BALLOT_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "__acceptAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "cancel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + } + ], + "name": "castVote", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "castVoteBySig", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "castVoteWithReason", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "castVoteWithReasonAndParams", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "castVoteWithReasonAndParamsBySig", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "clock", + "outputs": [ + { + "internalType": "uint48", + "name": "", + "type": "uint48" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "eip712Domain", + "outputs": [ + { + "internalType": "bytes1", + "name": "fields", + "type": "bytes1" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "version", + "type": "string" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "verifyingContract", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + }, + { + "internalType": "uint256[]", + "name": "extensions", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "execute", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "getProposalId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + } + ], + "name": "getVotes", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "getVotesWithParams", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasVoted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "hashProposal", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC1155BatchReceived", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC1155Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC721Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalDeadline", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalEta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "proposalNeedsQueuing", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalProposer", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proposalThreshold", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "name": "propose", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "queue", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + } + ], + "name": "quorum", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "relay", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "state", + "outputs": [ + { + "internalType": "enum IGovernor.ProposalState", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "timelock", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract ICompoundTimelock", + "name": "newTimelock", + "type": "address" + } + ], + "name": "updateTimelock", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "votingDelay", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "votingPeriod", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/GovernorTimelockControl.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/GovernorTimelockControl.json new file mode 100644 index 00000000..4014f0ae --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/GovernorTimelockControl.json @@ -0,0 +1,1417 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "GovernorTimelockControl", + "sourceName": "contracts/governance/extensions/GovernorTimelockControl.sol", + "abi": [ + { + "inputs": [], + "name": "FailedCall", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "voter", + "type": "address" + } + ], + "name": "GovernorAlreadyCastVote", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorAlreadyQueuedProposal", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorDisabledDeposit", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "proposer", + "type": "address" + }, + { + "internalType": "uint256", + "name": "votes", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "threshold", + "type": "uint256" + } + ], + "name": "GovernorInsufficientProposerVotes", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "targets", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "calldatas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "values", + "type": "uint256" + } + ], + "name": "GovernorInvalidProposalLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "voter", + "type": "address" + } + ], + "name": "GovernorInvalidSignature", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorInvalidVoteParams", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorInvalidVoteType", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "votingPeriod", + "type": "uint256" + } + ], + "name": "GovernorInvalidVotingPeriod", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorNonexistentProposal", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorNotQueuedProposal", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "GovernorOnlyExecutor", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorQueueNotImplemented", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "proposer", + "type": "address" + } + ], + "name": "GovernorRestrictedProposer", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "GovernorUnableToCancel", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "enum IGovernor.ProposalState", + "name": "current", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "expectedStates", + "type": "bytes32" + } + ], + "name": "GovernorUnexpectedProposalState", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "currentNonce", + "type": "uint256" + } + ], + "name": "InvalidAccountNonce", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidShortString", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "bits", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "SafeCastOverflowedUintDowncast", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "str", + "type": "string" + } + ], + "name": "StringTooLong", + "type": "error" + }, + { + "anonymous": false, + "inputs": [], + "name": "EIP712DomainChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "ProposalCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "proposer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "string[]", + "name": "signatures", + "type": "string[]" + }, + { + "indexed": false, + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "voteStart", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "voteEnd", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "name": "ProposalCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "ProposalExecuted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "etaSeconds", + "type": "uint256" + } + ], + "name": "ProposalQueued", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldTimelock", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newTimelock", + "type": "address" + } + ], + "name": "TimelockChange", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "weight", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "VoteCast", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "weight", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "VoteCastWithParams", + "type": "event" + }, + { + "inputs": [], + "name": "BALLOT_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CLOCK_MODE", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "COUNTING_MODE", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "EXTENDED_BALLOT_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "cancel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + } + ], + "name": "castVote", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "castVoteBySig", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "castVoteWithReason", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "castVoteWithReasonAndParams", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "castVoteWithReasonAndParamsBySig", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "clock", + "outputs": [ + { + "internalType": "uint48", + "name": "", + "type": "uint48" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "eip712Domain", + "outputs": [ + { + "internalType": "bytes1", + "name": "fields", + "type": "bytes1" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "version", + "type": "string" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "verifyingContract", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + }, + { + "internalType": "uint256[]", + "name": "extensions", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "execute", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "getProposalId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + } + ], + "name": "getVotes", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "getVotesWithParams", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasVoted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "hashProposal", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC1155BatchReceived", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC1155Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC721Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalDeadline", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalEta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "proposalNeedsQueuing", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalProposer", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proposalThreshold", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "name": "propose", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "queue", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + } + ], + "name": "quorum", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "relay", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "state", + "outputs": [ + { + "internalType": "enum IGovernor.ProposalState", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "timelock", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract TimelockController", + "name": "newTimelock", + "type": "address" + } + ], + "name": "updateTimelock", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "votingDelay", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "votingPeriod", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/GovernorVotes.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/GovernorVotes.json new file mode 100644 index 00000000..02b7c87a --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/GovernorVotes.json @@ -0,0 +1,1385 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "GovernorVotes", + "sourceName": "contracts/governance/extensions/GovernorVotes.sol", + "abi": [ + { + "inputs": [], + "name": "FailedCall", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "voter", + "type": "address" + } + ], + "name": "GovernorAlreadyCastVote", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorAlreadyQueuedProposal", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorDisabledDeposit", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "proposer", + "type": "address" + }, + { + "internalType": "uint256", + "name": "votes", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "threshold", + "type": "uint256" + } + ], + "name": "GovernorInsufficientProposerVotes", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "targets", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "calldatas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "values", + "type": "uint256" + } + ], + "name": "GovernorInvalidProposalLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "voter", + "type": "address" + } + ], + "name": "GovernorInvalidSignature", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorInvalidVoteParams", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorInvalidVoteType", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "votingPeriod", + "type": "uint256" + } + ], + "name": "GovernorInvalidVotingPeriod", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorNonexistentProposal", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorNotQueuedProposal", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "GovernorOnlyExecutor", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorQueueNotImplemented", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "proposer", + "type": "address" + } + ], + "name": "GovernorRestrictedProposer", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "GovernorUnableToCancel", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "enum IGovernor.ProposalState", + "name": "current", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "expectedStates", + "type": "bytes32" + } + ], + "name": "GovernorUnexpectedProposalState", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "currentNonce", + "type": "uint256" + } + ], + "name": "InvalidAccountNonce", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidShortString", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "bits", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "SafeCastOverflowedUintDowncast", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "str", + "type": "string" + } + ], + "name": "StringTooLong", + "type": "error" + }, + { + "anonymous": false, + "inputs": [], + "name": "EIP712DomainChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "ProposalCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "proposer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "string[]", + "name": "signatures", + "type": "string[]" + }, + { + "indexed": false, + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "voteStart", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "voteEnd", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "name": "ProposalCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "ProposalExecuted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "etaSeconds", + "type": "uint256" + } + ], + "name": "ProposalQueued", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "weight", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "VoteCast", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "weight", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "VoteCastWithParams", + "type": "event" + }, + { + "inputs": [], + "name": "BALLOT_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CLOCK_MODE", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "COUNTING_MODE", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "EXTENDED_BALLOT_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "cancel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + } + ], + "name": "castVote", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "castVoteBySig", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "castVoteWithReason", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "castVoteWithReasonAndParams", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "castVoteWithReasonAndParamsBySig", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "clock", + "outputs": [ + { + "internalType": "uint48", + "name": "", + "type": "uint48" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "eip712Domain", + "outputs": [ + { + "internalType": "bytes1", + "name": "fields", + "type": "bytes1" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "version", + "type": "string" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "verifyingContract", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + }, + { + "internalType": "uint256[]", + "name": "extensions", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "execute", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "getProposalId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + } + ], + "name": "getVotes", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "getVotesWithParams", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasVoted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "hashProposal", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC1155BatchReceived", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC1155Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC721Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalDeadline", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalEta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "proposalNeedsQueuing", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalProposer", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proposalThreshold", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "name": "propose", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "queue", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + } + ], + "name": "quorum", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "relay", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "state", + "outputs": [ + { + "internalType": "enum IGovernor.ProposalState", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "token", + "outputs": [ + { + "internalType": "contract IERC5805", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "votingDelay", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "votingPeriod", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/GovernorVotesQuorumFraction.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/GovernorVotesQuorumFraction.json new file mode 100644 index 00000000..4d221704 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/GovernorVotesQuorumFraction.json @@ -0,0 +1,1483 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "GovernorVotesQuorumFraction", + "sourceName": "contracts/governance/extensions/GovernorVotesQuorumFraction.sol", + "abi": [ + { + "inputs": [], + "name": "CheckpointUnorderedInsertion", + "type": "error" + }, + { + "inputs": [], + "name": "FailedCall", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "voter", + "type": "address" + } + ], + "name": "GovernorAlreadyCastVote", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorAlreadyQueuedProposal", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorDisabledDeposit", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "proposer", + "type": "address" + }, + { + "internalType": "uint256", + "name": "votes", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "threshold", + "type": "uint256" + } + ], + "name": "GovernorInsufficientProposerVotes", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "targets", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "calldatas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "values", + "type": "uint256" + } + ], + "name": "GovernorInvalidProposalLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "quorumNumerator", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "quorumDenominator", + "type": "uint256" + } + ], + "name": "GovernorInvalidQuorumFraction", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "voter", + "type": "address" + } + ], + "name": "GovernorInvalidSignature", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorInvalidVoteParams", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorInvalidVoteType", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "votingPeriod", + "type": "uint256" + } + ], + "name": "GovernorInvalidVotingPeriod", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorNonexistentProposal", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorNotQueuedProposal", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "GovernorOnlyExecutor", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorQueueNotImplemented", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "proposer", + "type": "address" + } + ], + "name": "GovernorRestrictedProposer", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "GovernorUnableToCancel", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "enum IGovernor.ProposalState", + "name": "current", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "expectedStates", + "type": "bytes32" + } + ], + "name": "GovernorUnexpectedProposalState", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "currentNonce", + "type": "uint256" + } + ], + "name": "InvalidAccountNonce", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidShortString", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "bits", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "SafeCastOverflowedUintDowncast", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "str", + "type": "string" + } + ], + "name": "StringTooLong", + "type": "error" + }, + { + "anonymous": false, + "inputs": [], + "name": "EIP712DomainChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "ProposalCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "proposer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "string[]", + "name": "signatures", + "type": "string[]" + }, + { + "indexed": false, + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "voteStart", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "voteEnd", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "name": "ProposalCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "ProposalExecuted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "etaSeconds", + "type": "uint256" + } + ], + "name": "ProposalQueued", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldQuorumNumerator", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newQuorumNumerator", + "type": "uint256" + } + ], + "name": "QuorumNumeratorUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "weight", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "VoteCast", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "weight", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "VoteCastWithParams", + "type": "event" + }, + { + "inputs": [], + "name": "BALLOT_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CLOCK_MODE", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "COUNTING_MODE", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "EXTENDED_BALLOT_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "cancel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + } + ], + "name": "castVote", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "castVoteBySig", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "castVoteWithReason", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "castVoteWithReasonAndParams", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "castVoteWithReasonAndParamsBySig", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "clock", + "outputs": [ + { + "internalType": "uint48", + "name": "", + "type": "uint48" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "eip712Domain", + "outputs": [ + { + "internalType": "bytes1", + "name": "fields", + "type": "bytes1" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "version", + "type": "string" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "verifyingContract", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + }, + { + "internalType": "uint256[]", + "name": "extensions", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "execute", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "getProposalId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + } + ], + "name": "getVotes", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "getVotesWithParams", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasVoted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "hashProposal", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC1155BatchReceived", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC1155Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC721Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalDeadline", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalEta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "proposalNeedsQueuing", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalProposer", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proposalThreshold", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "name": "propose", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "queue", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + } + ], + "name": "quorum", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "quorumDenominator", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + } + ], + "name": "quorumNumerator", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "quorumNumerator", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "relay", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "state", + "outputs": [ + { + "internalType": "enum IGovernor.ProposalState", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "token", + "outputs": [ + { + "internalType": "contract IERC5805", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newQuorumNumerator", + "type": "uint256" + } + ], + "name": "updateQuorumNumerator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "votingDelay", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "votingPeriod", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/GovernorVotesSuperQuorumFraction.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/GovernorVotesSuperQuorumFraction.json new file mode 100644 index 00000000..e20bfeaa --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/GovernorVotesSuperQuorumFraction.json @@ -0,0 +1,1643 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "GovernorVotesSuperQuorumFraction", + "sourceName": "contracts/governance/extensions/GovernorVotesSuperQuorumFraction.sol", + "abi": [ + { + "inputs": [], + "name": "CheckpointUnorderedInsertion", + "type": "error" + }, + { + "inputs": [], + "name": "FailedCall", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "voter", + "type": "address" + } + ], + "name": "GovernorAlreadyCastVote", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorAlreadyQueuedProposal", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorDisabledDeposit", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "proposer", + "type": "address" + }, + { + "internalType": "uint256", + "name": "votes", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "threshold", + "type": "uint256" + } + ], + "name": "GovernorInsufficientProposerVotes", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "targets", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "calldatas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "values", + "type": "uint256" + } + ], + "name": "GovernorInvalidProposalLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "quorumNumerator", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "quorumDenominator", + "type": "uint256" + } + ], + "name": "GovernorInvalidQuorumFraction", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "quorumNumerator", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "superQuorumNumerator", + "type": "uint256" + } + ], + "name": "GovernorInvalidQuorumTooLarge", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "voter", + "type": "address" + } + ], + "name": "GovernorInvalidSignature", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "superQuorumNumerator", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "denominator", + "type": "uint256" + } + ], + "name": "GovernorInvalidSuperQuorumFraction", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "superQuorumNumerator", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "quorumNumerator", + "type": "uint256" + } + ], + "name": "GovernorInvalidSuperQuorumTooSmall", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorInvalidVoteParams", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorInvalidVoteType", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "votingPeriod", + "type": "uint256" + } + ], + "name": "GovernorInvalidVotingPeriod", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorNonexistentProposal", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorNotQueuedProposal", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "GovernorOnlyExecutor", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorQueueNotImplemented", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "proposer", + "type": "address" + } + ], + "name": "GovernorRestrictedProposer", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "GovernorUnableToCancel", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "enum IGovernor.ProposalState", + "name": "current", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "expectedStates", + "type": "bytes32" + } + ], + "name": "GovernorUnexpectedProposalState", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "currentNonce", + "type": "uint256" + } + ], + "name": "InvalidAccountNonce", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidShortString", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "bits", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "SafeCastOverflowedUintDowncast", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "str", + "type": "string" + } + ], + "name": "StringTooLong", + "type": "error" + }, + { + "anonymous": false, + "inputs": [], + "name": "EIP712DomainChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "ProposalCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "proposer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "string[]", + "name": "signatures", + "type": "string[]" + }, + { + "indexed": false, + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "voteStart", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "voteEnd", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "name": "ProposalCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "ProposalExecuted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "etaSeconds", + "type": "uint256" + } + ], + "name": "ProposalQueued", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldQuorumNumerator", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newQuorumNumerator", + "type": "uint256" + } + ], + "name": "QuorumNumeratorUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldSuperQuorumNumerator", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newSuperQuorumNumerator", + "type": "uint256" + } + ], + "name": "SuperQuorumNumeratorUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "weight", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "VoteCast", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "weight", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "VoteCastWithParams", + "type": "event" + }, + { + "inputs": [], + "name": "BALLOT_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CLOCK_MODE", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "COUNTING_MODE", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "EXTENDED_BALLOT_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "cancel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + } + ], + "name": "castVote", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "castVoteBySig", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "castVoteWithReason", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "castVoteWithReasonAndParams", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "castVoteWithReasonAndParamsBySig", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "clock", + "outputs": [ + { + "internalType": "uint48", + "name": "", + "type": "uint48" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "eip712Domain", + "outputs": [ + { + "internalType": "bytes1", + "name": "fields", + "type": "bytes1" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "version", + "type": "string" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "verifyingContract", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + }, + { + "internalType": "uint256[]", + "name": "extensions", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "execute", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "getProposalId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + } + ], + "name": "getVotes", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "getVotesWithParams", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasVoted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "hashProposal", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC1155BatchReceived", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC1155Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC721Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalDeadline", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalEta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "proposalNeedsQueuing", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalProposer", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proposalThreshold", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalVotes", + "outputs": [ + { + "internalType": "uint256", + "name": "againstVotes", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "forVotes", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "abstainVotes", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "name": "propose", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "queue", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + } + ], + "name": "quorum", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "quorumDenominator", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + } + ], + "name": "quorumNumerator", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "quorumNumerator", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "relay", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "state", + "outputs": [ + { + "internalType": "enum IGovernor.ProposalState", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + } + ], + "name": "superQuorum", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "superQuorumNumerator", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + } + ], + "name": "superQuorumNumerator", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "token", + "outputs": [ + { + "internalType": "contract IERC5805", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newQuorumNumerator", + "type": "uint256" + } + ], + "name": "updateQuorumNumerator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newSuperQuorumNumerator", + "type": "uint256" + } + ], + "name": "updateSuperQuorumNumerator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "votingDelay", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "votingPeriod", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Hashes.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Hashes.json new file mode 100644 index 00000000..9271985c --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Hashes.json @@ -0,0 +1,10 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "Hashes", + "sourceName": "contracts/utils/cryptography/Hashes.sol", + "abi": [], + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212208d74f124b0b195abcc7e3d14f3f42d9043d1679b77161032c4fa3ebe20d5946a64736f6c634300081b0033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212208d74f124b0b195abcc7e3d14f3f42d9043d1679b77161032c4fa3ebe20d5946a64736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Heap.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Heap.json new file mode 100644 index 00000000..9d12b7df --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Heap.json @@ -0,0 +1,10 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "Heap", + "sourceName": "contracts/utils/structs/Heap.sol", + "abi": [], + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122043fbf66e6090d120b0eb77148fbeeb3e89dcb0312cd8146d943b4594a0d05d4d64736f6c634300081b0033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122043fbf66e6090d120b0eb77148fbeeb3e89dcb0312cd8146d943b4594a0d05d4d64736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IAccessControl.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IAccessControl.json new file mode 100644 index 00000000..053c7acb --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IAccessControl.json @@ -0,0 +1,204 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IAccessControl", + "sourceName": "contracts/access/IAccessControl.sol", + "abi": [ + { + "inputs": [], + "name": "AccessControlBadConfirmation", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "neededRole", + "type": "bytes32" + } + ], + "name": "AccessControlUnauthorizedAccount", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "callerConfirmation", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IAccessControlDefaultAdminRules.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IAccessControlDefaultAdminRules.json new file mode 100644 index 00000000..ccf48bb1 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IAccessControlDefaultAdminRules.json @@ -0,0 +1,403 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IAccessControlDefaultAdminRules", + "sourceName": "contracts/access/extensions/IAccessControlDefaultAdminRules.sol", + "abi": [ + { + "inputs": [], + "name": "AccessControlBadConfirmation", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint48", + "name": "schedule", + "type": "uint48" + } + ], + "name": "AccessControlEnforcedDefaultAdminDelay", + "type": "error" + }, + { + "inputs": [], + "name": "AccessControlEnforcedDefaultAdminRules", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "defaultAdmin", + "type": "address" + } + ], + "name": "AccessControlInvalidDefaultAdmin", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "neededRole", + "type": "bytes32" + } + ], + "name": "AccessControlUnauthorizedAccount", + "type": "error" + }, + { + "anonymous": false, + "inputs": [], + "name": "DefaultAdminDelayChangeCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint48", + "name": "newDelay", + "type": "uint48" + }, + { + "indexed": false, + "internalType": "uint48", + "name": "effectSchedule", + "type": "uint48" + } + ], + "name": "DefaultAdminDelayChangeScheduled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "DefaultAdminTransferCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "newAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint48", + "name": "acceptSchedule", + "type": "uint48" + } + ], + "name": "DefaultAdminTransferScheduled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "inputs": [], + "name": "acceptDefaultAdminTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "beginDefaultAdminTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "cancelDefaultAdminTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint48", + "name": "newDelay", + "type": "uint48" + } + ], + "name": "changeDefaultAdminDelay", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "defaultAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "defaultAdminDelay", + "outputs": [ + { + "internalType": "uint48", + "name": "", + "type": "uint48" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "defaultAdminDelayIncreaseWait", + "outputs": [ + { + "internalType": "uint48", + "name": "", + "type": "uint48" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingDefaultAdmin", + "outputs": [ + { + "internalType": "address", + "name": "newAdmin", + "type": "address" + }, + { + "internalType": "uint48", + "name": "acceptSchedule", + "type": "uint48" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingDefaultAdminDelay", + "outputs": [ + { + "internalType": "uint48", + "name": "newDelay", + "type": "uint48" + }, + { + "internalType": "uint48", + "name": "effectSchedule", + "type": "uint48" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "callerConfirmation", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "rollbackDefaultAdminDelay", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IAccessControlEnumerable.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IAccessControlEnumerable.json new file mode 100644 index 00000000..a11f9cac --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IAccessControlEnumerable.json @@ -0,0 +1,247 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IAccessControlEnumerable", + "sourceName": "contracts/access/extensions/IAccessControlEnumerable.sol", + "abi": [ + { + "inputs": [], + "name": "AccessControlBadConfirmation", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "neededRole", + "type": "bytes32" + } + ], + "name": "AccessControlUnauthorizedAccount", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "getRoleMember", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleMemberCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "callerConfirmation", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IAccessManaged.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IAccessManaged.json new file mode 100644 index 00000000..3691db30 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IAccessManaged.json @@ -0,0 +1,101 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IAccessManaged", + "sourceName": "contracts/access/manager/IAccessManaged.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "authority", + "type": "address" + } + ], + "name": "AccessManagedInvalidAuthority", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "internalType": "uint32", + "name": "delay", + "type": "uint32" + } + ], + "name": "AccessManagedRequiredDelay", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "caller", + "type": "address" + } + ], + "name": "AccessManagedUnauthorized", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "authority", + "type": "address" + } + ], + "name": "AuthorityUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "authority", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isConsumingScheduledOp", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "setAuthority", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IAccessManager.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IAccessManager.json new file mode 100644 index 00000000..e0d18f70 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IAccessManager.json @@ -0,0 +1,1071 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IAccessManager", + "sourceName": "contracts/access/manager/IAccessManager.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "bytes32", + "name": "operationId", + "type": "bytes32" + } + ], + "name": "AccessManagerAlreadyScheduled", + "type": "error" + }, + { + "inputs": [], + "name": "AccessManagerBadConfirmation", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "operationId", + "type": "bytes32" + } + ], + "name": "AccessManagerExpired", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "initialAdmin", + "type": "address" + } + ], + "name": "AccessManagerInvalidInitialAdmin", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "roleId", + "type": "uint64" + } + ], + "name": "AccessManagerLockedRole", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "operationId", + "type": "bytes32" + } + ], + "name": "AccessManagerNotReady", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "operationId", + "type": "bytes32" + } + ], + "name": "AccessManagerNotScheduled", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "msgsender", + "type": "address" + }, + { + "internalType": "uint64", + "name": "roleId", + "type": "uint64" + } + ], + "name": "AccessManagerUnauthorizedAccount", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes4", + "name": "selector", + "type": "bytes4" + } + ], + "name": "AccessManagerUnauthorizedCall", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "msgsender", + "type": "address" + }, + { + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes4", + "name": "selector", + "type": "bytes4" + } + ], + "name": "AccessManagerUnauthorizedCancel", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "AccessManagerUnauthorizedConsume", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "operationId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "uint32", + "name": "nonce", + "type": "uint32" + } + ], + "name": "OperationCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "operationId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "uint32", + "name": "nonce", + "type": "uint32" + } + ], + "name": "OperationExecuted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "operationId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "uint32", + "name": "nonce", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint48", + "name": "schedule", + "type": "uint48" + }, + { + "indexed": false, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "OperationScheduled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "roleId", + "type": "uint64" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "admin", + "type": "uint64" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "roleId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "delay", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint48", + "name": "since", + "type": "uint48" + } + ], + "name": "RoleGrantDelayChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "roleId", + "type": "uint64" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "delay", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint48", + "name": "since", + "type": "uint48" + }, + { + "indexed": false, + "internalType": "bool", + "name": "newMember", + "type": "bool" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "roleId", + "type": "uint64" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "guardian", + "type": "uint64" + } + ], + "name": "RoleGuardianChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "roleId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "RoleLabel", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "roleId", + "type": "uint64" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "delay", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint48", + "name": "since", + "type": "uint48" + } + ], + "name": "TargetAdminDelayUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "closed", + "type": "bool" + } + ], + "name": "TargetClosed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes4", + "name": "selector", + "type": "bytes4" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "roleId", + "type": "uint64" + } + ], + "name": "TargetFunctionRoleUpdated", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes4", + "name": "selector", + "type": "bytes4" + } + ], + "name": "canCall", + "outputs": [ + { + "internalType": "bool", + "name": "allowed", + "type": "bool" + }, + { + "internalType": "uint32", + "name": "delay", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "cancel", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "consumeScheduledOp", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "execute", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "expiration", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "roleId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccess", + "outputs": [ + { + "internalType": "uint48", + "name": "since", + "type": "uint48" + }, + { + "internalType": "uint32", + "name": "currentDelay", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "pendingDelay", + "type": "uint32" + }, + { + "internalType": "uint48", + "name": "effect", + "type": "uint48" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "getNonce", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "roleId", + "type": "uint64" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "roleId", + "type": "uint64" + } + ], + "name": "getRoleGrantDelay", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "roleId", + "type": "uint64" + } + ], + "name": "getRoleGuardian", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "getSchedule", + "outputs": [ + { + "internalType": "uint48", + "name": "", + "type": "uint48" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "getTargetAdminDelay", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes4", + "name": "selector", + "type": "bytes4" + } + ], + "name": "getTargetFunctionRole", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "roleId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint32", + "name": "executionDelay", + "type": "uint32" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "roleId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "isMember", + "type": "bool" + }, + { + "internalType": "uint32", + "name": "executionDelay", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "hashOperation", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "isTargetClosed", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "roleId", + "type": "uint64" + }, + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "labelRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "minSetback", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "roleId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "callerConfirmation", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "roleId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "uint48", + "name": "when", + "type": "uint48" + } + ], + "name": "schedule", + "outputs": [ + { + "internalType": "bytes32", + "name": "operationId", + "type": "bytes32" + }, + { + "internalType": "uint32", + "name": "nonce", + "type": "uint32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "roleId", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "newDelay", + "type": "uint32" + } + ], + "name": "setGrantDelay", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "roleId", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "admin", + "type": "uint64" + } + ], + "name": "setRoleAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "roleId", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "guardian", + "type": "uint64" + } + ], + "name": "setRoleGuardian", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint32", + "name": "newDelay", + "type": "uint32" + } + ], + "name": "setTargetAdminDelay", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bool", + "name": "closed", + "type": "bool" + } + ], + "name": "setTargetClosed", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes4[]", + "name": "selectors", + "type": "bytes4[]" + }, + { + "internalType": "uint64", + "name": "roleId", + "type": "uint64" + } + ], + "name": "setTargetFunctionRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "address", + "name": "newAuthority", + "type": "address" + } + ], + "name": "updateAuthority", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IAccount.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IAccount.json new file mode 100644 index 00000000..7133e434 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IAccount.json @@ -0,0 +1,87 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IAccount", + "sourceName": "contracts/interfaces/draft-IERC4337.sol", + "abi": [ + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "initCode", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "callData", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "accountGasLimits", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "preVerificationGas", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "gasFees", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "paymasterAndData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "internalType": "struct PackedUserOperation", + "name": "userOp", + "type": "tuple" + }, + { + "internalType": "bytes32", + "name": "userOpHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "missingAccountFunds", + "type": "uint256" + } + ], + "name": "validateUserOp", + "outputs": [ + { + "internalType": "uint256", + "name": "validationData", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IAccountExecute.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IAccountExecute.json new file mode 100644 index 00000000..750f602d --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IAccountExecute.json @@ -0,0 +1,76 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IAccountExecute", + "sourceName": "contracts/interfaces/draft-IERC4337.sol", + "abi": [ + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "initCode", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "callData", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "accountGasLimits", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "preVerificationGas", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "gasFees", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "paymasterAndData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "internalType": "struct PackedUserOperation", + "name": "userOp", + "type": "tuple" + }, + { + "internalType": "bytes32", + "name": "userOpHash", + "type": "bytes32" + } + ], + "name": "executeUserOp", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IAggregator.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IAggregator.json new file mode 100644 index 00000000..cc320ad2 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IAggregator.json @@ -0,0 +1,208 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IAggregator", + "sourceName": "contracts/interfaces/draft-IERC4337.sol", + "abi": [ + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "initCode", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "callData", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "accountGasLimits", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "preVerificationGas", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "gasFees", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "paymasterAndData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "internalType": "struct PackedUserOperation[]", + "name": "userOps", + "type": "tuple[]" + } + ], + "name": "aggregateSignatures", + "outputs": [ + { + "internalType": "bytes", + "name": "aggregatesSignature", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "initCode", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "callData", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "accountGasLimits", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "preVerificationGas", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "gasFees", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "paymasterAndData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "internalType": "struct PackedUserOperation[]", + "name": "userOps", + "type": "tuple[]" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "validateSignatures", + "outputs": [], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "initCode", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "callData", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "accountGasLimits", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "preVerificationGas", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "gasFees", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "paymasterAndData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "internalType": "struct PackedUserOperation", + "name": "userOp", + "type": "tuple" + } + ], + "name": "validateUserOpSignature", + "outputs": [ + { + "internalType": "bytes", + "name": "sigForUserOp", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IAuthority.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IAuthority.json new file mode 100644 index 00000000..06983267 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IAuthority.json @@ -0,0 +1,40 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IAuthority", + "sourceName": "contracts/access/manager/IAuthority.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes4", + "name": "selector", + "type": "bytes4" + } + ], + "name": "canCall", + "outputs": [ + { + "internalType": "bool", + "name": "allowed", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IBeacon.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IBeacon.json new file mode 100644 index 00000000..6b88dda0 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IBeacon.json @@ -0,0 +1,24 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IBeacon", + "sourceName": "contracts/proxy/beacon/IBeacon.sol", + "abi": [ + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ICompoundTimelock.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ICompoundTimelock.json new file mode 100644 index 00000000..d6ba37fd --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ICompoundTimelock.json @@ -0,0 +1,424 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ICompoundTimelock", + "sourceName": "contracts/vendor/compound/ICompoundTimelock.sol", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txHash", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "signature", + "type": "string" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "eta", + "type": "uint256" + } + ], + "name": "CancelTransaction", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txHash", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "signature", + "type": "string" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "eta", + "type": "uint256" + } + ], + "name": "ExecuteTransaction", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "newDelay", + "type": "uint256" + } + ], + "name": "NewDelay", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txHash", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "signature", + "type": "string" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "eta", + "type": "uint256" + } + ], + "name": "QueueTransaction", + "type": "event" + }, + { + "inputs": [], + "name": "GRACE_PERIOD", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAXIMUM_DELAY", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MINIMUM_DELAY", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "string", + "name": "signature", + "type": "string" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "eta", + "type": "uint256" + } + ], + "name": "cancelTransaction", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "delay", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "string", + "name": "signature", + "type": "string" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "eta", + "type": "uint256" + } + ], + "name": "executeTransaction", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "string", + "name": "signature", + "type": "string" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "eta", + "type": "uint256" + } + ], + "name": "queueTransaction", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "queuedTransactions", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "setDelay", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "setPendingAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC1155.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC1155.json new file mode 100644 index 00000000..871f465a --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC1155.json @@ -0,0 +1,304 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IERC1155", + "sourceName": "contracts/token/ERC1155/IERC1155.sol", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "ApprovalForAll", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + } + ], + "name": "TransferBatch", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "TransferSingle", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "value", + "type": "string" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "URI", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "accounts", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + } + ], + "name": "balanceOfBatch", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "isApprovedForAll", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeBatchTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setApprovalForAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC1155Errors.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC1155Errors.json new file mode 100644 index 00000000..a8fd8614 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC1155Errors.json @@ -0,0 +1,113 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IERC1155Errors", + "sourceName": "contracts/interfaces/draft-IERC6093.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ERC1155InsufficientBalance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "approver", + "type": "address" + } + ], + "name": "ERC1155InvalidApprover", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "idsLength", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "valuesLength", + "type": "uint256" + } + ], + "name": "ERC1155InvalidArrayLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "ERC1155InvalidOperator", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ERC1155InvalidReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ERC1155InvalidSender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "ERC1155MissingApprovalForAll", + "type": "error" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC1155MetadataURI.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC1155MetadataURI.json new file mode 100644 index 00000000..aaca2243 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC1155MetadataURI.json @@ -0,0 +1,323 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IERC1155MetadataURI", + "sourceName": "contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "ApprovalForAll", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + } + ], + "name": "TransferBatch", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "TransferSingle", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "value", + "type": "string" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "URI", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "accounts", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + } + ], + "name": "balanceOfBatch", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "isApprovedForAll", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeBatchTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setApprovalForAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "uri", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC1155Receiver.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC1155Receiver.json new file mode 100644 index 00000000..e8ab4d51 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC1155Receiver.json @@ -0,0 +1,108 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IERC1155Receiver", + "sourceName": "contracts/token/ERC1155/IERC1155Receiver.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onERC1155BatchReceived", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onERC1155Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC1271.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC1271.json new file mode 100644 index 00000000..abfe1cc1 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC1271.json @@ -0,0 +1,35 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IERC1271", + "sourceName": "contracts/interfaces/IERC1271.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "isValidSignature", + "outputs": [ + { + "internalType": "bytes4", + "name": "magicValue", + "type": "bytes4" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC1363.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC1363.json new file mode 100644 index 00000000..03df25ce --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC1363.json @@ -0,0 +1,382 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IERC1363", + "sourceName": "contracts/interfaces/IERC1363.sol", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "approveAndCall", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "approveAndCall", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferAndCall", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "transferAndCall", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "transferFromAndCall", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferFromAndCall", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC1363Receiver.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC1363Receiver.json new file mode 100644 index 00000000..13fac203 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC1363Receiver.json @@ -0,0 +1,45 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IERC1363Receiver", + "sourceName": "contracts/interfaces/IERC1363Receiver.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onTransferReceived", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC1363Spender.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC1363Spender.json new file mode 100644 index 00000000..8d15a158 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC1363Spender.json @@ -0,0 +1,40 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IERC1363Spender", + "sourceName": "contracts/interfaces/IERC1363Spender.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onApprovalReceived", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC165.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC165.json new file mode 100644 index 00000000..7152c3eb --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC165.json @@ -0,0 +1,30 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IERC165", + "sourceName": "contracts/utils/introspection/IERC165.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC1820Implementer.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC1820Implementer.json new file mode 100644 index 00000000..2f133187 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC1820Implementer.json @@ -0,0 +1,35 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IERC1820Implementer", + "sourceName": "contracts/interfaces/IERC1820Implementer.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "bytes32", + "name": "interfaceHash", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "canImplementInterfaceForAddress", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC1820Registry.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC1820Registry.json new file mode 100644 index 00000000..219465ae --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC1820Registry.json @@ -0,0 +1,224 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IERC1820Registry", + "sourceName": "contracts/interfaces/IERC1820Registry.sol", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "interfaceHash", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "implementer", + "type": "address" + } + ], + "name": "InterfaceImplementerSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newManager", + "type": "address" + } + ], + "name": "ManagerChanged", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "_interfaceHash", + "type": "bytes32" + } + ], + "name": "getInterfaceImplementer", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "implementsERC165Interface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "implementsERC165InterfaceNoCache", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "interfaceName", + "type": "string" + } + ], + "name": "interfaceHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "_interfaceHash", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "implementer", + "type": "address" + } + ], + "name": "setInterfaceImplementer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "address", + "name": "newManager", + "type": "address" + } + ], + "name": "setManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "updateERC165Cache", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC1822Proxiable.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC1822Proxiable.json new file mode 100644 index 00000000..7e57cfa0 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC1822Proxiable.json @@ -0,0 +1,24 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IERC1822Proxiable", + "sourceName": "contracts/interfaces/draft-IERC1822.sol", + "abi": [ + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC1967.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC1967.json new file mode 100644 index 00000000..6bb0542c --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC1967.json @@ -0,0 +1,56 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IERC1967", + "sourceName": "contracts/interfaces/IERC1967.sol", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC20.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC20.json new file mode 100644 index 00000000..6dad1476 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC20.json @@ -0,0 +1,194 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IERC20", + "sourceName": "contracts/token/ERC20/IERC20.sol", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC20Errors.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC20Errors.json new file mode 100644 index 00000000..df9b5fb1 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC20Errors.json @@ -0,0 +1,97 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IERC20Errors", + "sourceName": "contracts/interfaces/draft-IERC6093.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "allowance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + } + ], + "name": "ERC20InsufficientAllowance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + } + ], + "name": "ERC20InsufficientBalance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "approver", + "type": "address" + } + ], + "name": "ERC20InvalidApprover", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ERC20InvalidReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ERC20InvalidSender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "ERC20InvalidSpender", + "type": "error" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC20Metadata.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC20Metadata.json new file mode 100644 index 00000000..8979e3ab --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC20Metadata.json @@ -0,0 +1,233 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IERC20Metadata", + "sourceName": "contracts/token/ERC20/extensions/IERC20Metadata.sol", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC20Permit.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC20Permit.json new file mode 100644 index 00000000..5a1893e3 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC20Permit.json @@ -0,0 +1,86 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IERC20Permit", + "sourceName": "contracts/token/ERC20/extensions/IERC20Permit.sol", + "abi": [ + { + "inputs": [], + "name": "DOMAIN_SEPARATOR", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "permit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC2309.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC2309.json new file mode 100644 index 00000000..46bdb349 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC2309.json @@ -0,0 +1,42 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IERC2309", + "sourceName": "contracts/interfaces/IERC2309.sol", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "fromTokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "toTokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "fromAddress", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "toAddress", + "type": "address" + } + ], + "name": "ConsecutiveTransfer", + "type": "event" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC2612.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC2612.json new file mode 100644 index 00000000..334751d7 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC2612.json @@ -0,0 +1,86 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IERC2612", + "sourceName": "contracts/interfaces/IERC2612.sol", + "abi": [ + { + "inputs": [], + "name": "DOMAIN_SEPARATOR", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "permit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC2981.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC2981.json new file mode 100644 index 00000000..d4dc531f --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC2981.json @@ -0,0 +1,59 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IERC2981", + "sourceName": "contracts/interfaces/IERC2981.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "salePrice", + "type": "uint256" + } + ], + "name": "royaltyInfo", + "outputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "royaltyAmount", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC3156FlashBorrower.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC3156FlashBorrower.json new file mode 100644 index 00000000..170493ff --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC3156FlashBorrower.json @@ -0,0 +1,50 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IERC3156FlashBorrower", + "sourceName": "contracts/interfaces/IERC3156FlashBorrower.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "initiator", + "type": "address" + }, + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fee", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onFlashLoan", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC3156FlashLender.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC3156FlashLender.json new file mode 100644 index 00000000..d4c75d3f --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC3156FlashLender.json @@ -0,0 +1,88 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IERC3156FlashLender", + "sourceName": "contracts/interfaces/IERC3156FlashLender.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "flashFee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC3156FlashBorrower", + "name": "receiver", + "type": "address" + }, + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "flashLoan", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "maxFlashLoan", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC4626.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC4626.json new file mode 100644 index 00000000..c333c6c0 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC4626.json @@ -0,0 +1,623 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IERC4626", + "sourceName": "contracts/interfaces/IERC4626.sol", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "Deposit", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "Withdraw", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "asset", + "outputs": [ + { + "internalType": "address", + "name": "assetTokenAddress", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "convertToAssets", + "outputs": [ + { + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "name": "convertToShares", + "outputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "assets", + "type": "uint256" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "deposit", + "outputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "maxDeposit", + "outputs": [ + { + "internalType": "uint256", + "name": "maxAssets", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "maxMint", + "outputs": [ + { + "internalType": "uint256", + "name": "maxShares", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "maxRedeem", + "outputs": [ + { + "internalType": "uint256", + "name": "maxShares", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "maxWithdraw", + "outputs": [ + { + "internalType": "uint256", + "name": "maxAssets", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "name": "previewDeposit", + "outputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "previewMint", + "outputs": [ + { + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "previewRedeem", + "outputs": [ + { + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "name": "previewWithdraw", + "outputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "redeem", + "outputs": [ + { + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalAssets", + "outputs": [ + { + "internalType": "uint256", + "name": "totalManagedAssets", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "assets", + "type": "uint256" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "withdraw", + "outputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC4906.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC4906.json new file mode 100644 index 00000000..5af9eb42 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC4906.json @@ -0,0 +1,328 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IERC4906", + "sourceName": "contracts/interfaces/IERC4906.sol", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "approved", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "ApprovalForAll", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "_fromTokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_toTokenId", + "type": "uint256" + } + ], + "name": "BatchMetadataUpdate", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "MetadataUpdate", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "getApproved", + "outputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "isApprovedForAll", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ownerOf", + "outputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setApprovalForAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC5267.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC5267.json new file mode 100644 index 00000000..102168a4 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC5267.json @@ -0,0 +1,60 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IERC5267", + "sourceName": "contracts/interfaces/IERC5267.sol", + "abi": [ + { + "anonymous": false, + "inputs": [], + "name": "EIP712DomainChanged", + "type": "event" + }, + { + "inputs": [], + "name": "eip712Domain", + "outputs": [ + { + "internalType": "bytes1", + "name": "fields", + "type": "bytes1" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "version", + "type": "string" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "verifyingContract", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + }, + { + "internalType": "uint256[]", + "name": "extensions", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC5313.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC5313.json new file mode 100644 index 00000000..098b345c --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC5313.json @@ -0,0 +1,24 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IERC5313", + "sourceName": "contracts/interfaces/IERC5313.sol", + "abi": [ + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC5805.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC5805.json new file mode 100644 index 00000000..2f6c3445 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC5805.json @@ -0,0 +1,230 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IERC5805", + "sourceName": "contracts/interfaces/IERC5805.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "uint256", + "name": "expiry", + "type": "uint256" + } + ], + "name": "VotesExpiredSignature", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "delegator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "fromDelegate", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "toDelegate", + "type": "address" + } + ], + "name": "DelegateChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "delegate", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "previousVotes", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newVotes", + "type": "uint256" + } + ], + "name": "DelegateVotesChanged", + "type": "event" + }, + { + "inputs": [], + "name": "CLOCK_MODE", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "clock", + "outputs": [ + { + "internalType": "uint48", + "name": "", + "type": "uint48" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "delegatee", + "type": "address" + } + ], + "name": "delegate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "delegatee", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "expiry", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "delegateBySig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "delegates", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + } + ], + "name": "getPastTotalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + } + ], + "name": "getPastVotes", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getVotes", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC6372.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC6372.json new file mode 100644 index 00000000..c82d7198 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC6372.json @@ -0,0 +1,37 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IERC6372", + "sourceName": "contracts/interfaces/IERC6372.sol", + "abi": [ + { + "inputs": [], + "name": "CLOCK_MODE", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "clock", + "outputs": [ + { + "internalType": "uint48", + "name": "", + "type": "uint48" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC6909.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC6909.json new file mode 100644 index 00000000..97bfe838 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC6909.json @@ -0,0 +1,316 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IERC6909", + "sourceName": "contracts/interfaces/draft-IERC6909.sol", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "OperatorSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "isOperator", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setOperator", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC6909ContentURI.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC6909ContentURI.json new file mode 100644 index 00000000..250843ce --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC6909ContentURI.json @@ -0,0 +1,348 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IERC6909ContentURI", + "sourceName": "contracts/interfaces/draft-IERC6909.sol", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "OperatorSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "contractURI", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "isOperator", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setOperator", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "tokenURI", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC6909Metadata.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC6909Metadata.json new file mode 100644 index 00000000..2e7d2b08 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC6909Metadata.json @@ -0,0 +1,373 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IERC6909Metadata", + "sourceName": "contracts/interfaces/draft-IERC6909.sol", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "OperatorSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "isOperator", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setOperator", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC6909TokenSupply.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC6909TokenSupply.json new file mode 100644 index 00000000..538c66ec --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC6909TokenSupply.json @@ -0,0 +1,335 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IERC6909TokenSupply", + "sourceName": "contracts/interfaces/draft-IERC6909.sol", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "OperatorSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "isOperator", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setOperator", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC721.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC721.json new file mode 100644 index 00000000..e3a12316 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC721.json @@ -0,0 +1,296 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IERC721", + "sourceName": "contracts/token/ERC721/IERC721.sol", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "approved", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "ApprovalForAll", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "getApproved", + "outputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "isApprovedForAll", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ownerOf", + "outputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setApprovalForAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC721Enumerable.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC721Enumerable.json new file mode 100644 index 00000000..a9c1b6d8 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC721Enumerable.json @@ -0,0 +1,352 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IERC721Enumerable", + "sourceName": "contracts/token/ERC721/extensions/IERC721Enumerable.sol", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "approved", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "ApprovalForAll", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "getApproved", + "outputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "isApprovedForAll", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ownerOf", + "outputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setApprovalForAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "tokenByIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "tokenOfOwnerByIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC721Errors.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC721Errors.json new file mode 100644 index 00000000..12f73984 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC721Errors.json @@ -0,0 +1,114 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IERC721Errors", + "sourceName": "contracts/interfaces/draft-IERC6093.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "ERC721IncorrectOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ERC721InsufficientApproval", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "approver", + "type": "address" + } + ], + "name": "ERC721InvalidApprover", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "ERC721InvalidOperator", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "ERC721InvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ERC721InvalidReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ERC721InvalidSender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ERC721NonexistentToken", + "type": "error" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC721Metadata.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC721Metadata.json new file mode 100644 index 00000000..baab9220 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC721Metadata.json @@ -0,0 +1,341 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IERC721Metadata", + "sourceName": "contracts/token/ERC721/extensions/IERC721Metadata.sol", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "approved", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "ApprovalForAll", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "getApproved", + "outputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "isApprovedForAll", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ownerOf", + "outputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setApprovalForAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "tokenURI", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC721Receiver.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC721Receiver.json new file mode 100644 index 00000000..d2e10c5d --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC721Receiver.json @@ -0,0 +1,45 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IERC721Receiver", + "sourceName": "contracts/token/ERC721/IERC721Receiver.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onERC721Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC7579AccountConfig.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC7579AccountConfig.json new file mode 100644 index 00000000..f3cd1318 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC7579AccountConfig.json @@ -0,0 +1,62 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IERC7579AccountConfig", + "sourceName": "contracts/interfaces/draft-IERC7579.sol", + "abi": [ + { + "inputs": [], + "name": "accountId", + "outputs": [ + { + "internalType": "string", + "name": "accountImplementationId", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "encodedMode", + "type": "bytes32" + } + ], + "name": "supportsExecutionMode", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "moduleTypeId", + "type": "uint256" + } + ], + "name": "supportsModule", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC7579Execution.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC7579Execution.json new file mode 100644 index 00000000..a3946d3e --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC7579Execution.json @@ -0,0 +1,53 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IERC7579Execution", + "sourceName": "contracts/interfaces/draft-IERC7579.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "bytes32", + "name": "mode", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "executionCalldata", + "type": "bytes" + } + ], + "name": "execute", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "mode", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "executionCalldata", + "type": "bytes" + } + ], + "name": "executeFromExecutor", + "outputs": [ + { + "internalType": "bytes[]", + "name": "returnData", + "type": "bytes[]" + } + ], + "stateMutability": "payable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC7579Hook.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC7579Hook.json new file mode 100644 index 00000000..7d076ccb --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC7579Hook.json @@ -0,0 +1,98 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IERC7579Hook", + "sourceName": "contracts/interfaces/draft-IERC7579.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "uint256", + "name": "moduleTypeId", + "type": "uint256" + } + ], + "name": "isModuleType", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onInstall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onUninstall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "hookData", + "type": "bytes" + } + ], + "name": "postCheck", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "msgSender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "msgData", + "type": "bytes" + } + ], + "name": "preCheck", + "outputs": [ + { + "internalType": "bytes", + "name": "hookData", + "type": "bytes" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC7579Module.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC7579Module.json new file mode 100644 index 00000000..9c3acbdf --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC7579Module.json @@ -0,0 +1,56 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IERC7579Module", + "sourceName": "contracts/interfaces/draft-IERC7579.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "uint256", + "name": "moduleTypeId", + "type": "uint256" + } + ], + "name": "isModuleType", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onInstall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onUninstall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC7579ModuleConfig.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC7579ModuleConfig.json new file mode 100644 index 00000000..08eeb03e --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC7579ModuleConfig.json @@ -0,0 +1,124 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IERC7579ModuleConfig", + "sourceName": "contracts/interfaces/draft-IERC7579.sol", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "moduleTypeId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "module", + "type": "address" + } + ], + "name": "ModuleInstalled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "moduleTypeId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "module", + "type": "address" + } + ], + "name": "ModuleUninstalled", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "moduleTypeId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "module", + "type": "address" + }, + { + "internalType": "bytes", + "name": "initData", + "type": "bytes" + } + ], + "name": "installModule", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "moduleTypeId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "module", + "type": "address" + }, + { + "internalType": "bytes", + "name": "additionalContext", + "type": "bytes" + } + ], + "name": "isModuleInstalled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "moduleTypeId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "module", + "type": "address" + }, + { + "internalType": "bytes", + "name": "deInitData", + "type": "bytes" + } + ], + "name": "uninstallModule", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC7579Validator.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC7579Validator.json new file mode 100644 index 00000000..2b75cdd5 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC7579Validator.json @@ -0,0 +1,156 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IERC7579Validator", + "sourceName": "contracts/interfaces/draft-IERC7579.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "uint256", + "name": "moduleTypeId", + "type": "uint256" + } + ], + "name": "isModuleType", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "isValidSignatureWithSender", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onInstall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onUninstall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "initCode", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "callData", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "accountGasLimits", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "preVerificationGas", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "gasFees", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "paymasterAndData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "internalType": "struct PackedUserOperation", + "name": "userOp", + "type": "tuple" + }, + { + "internalType": "bytes32", + "name": "userOpHash", + "type": "bytes32" + } + ], + "name": "validateUserOp", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC7674.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC7674.json new file mode 100644 index 00000000..8a5b080c --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC7674.json @@ -0,0 +1,218 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IERC7674", + "sourceName": "contracts/interfaces/draft-IERC7674.sol", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "temporaryApprove", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC777.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC777.json new file mode 100644 index 00000000..2adb9d15 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC777.json @@ -0,0 +1,402 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IERC777", + "sourceName": "contracts/interfaces/IERC777.sol", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenHolder", + "type": "address" + } + ], + "name": "AuthorizedOperator", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "operatorData", + "type": "bytes" + } + ], + "name": "Burned", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "operatorData", + "type": "bytes" + } + ], + "name": "Minted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenHolder", + "type": "address" + } + ], + "name": "RevokedOperator", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "operatorData", + "type": "bytes" + } + ], + "name": "Sent", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "authorizeOperator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "defaultOperators", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "granularity", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenHolder", + "type": "address" + } + ], + "name": "isOperatorFor", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "operatorData", + "type": "bytes" + } + ], + "name": "operatorBurn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "operatorData", + "type": "bytes" + } + ], + "name": "operatorSend", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "revokeOperator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "send", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC777Recipient.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC777Recipient.json new file mode 100644 index 00000000..dfd4a19f --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC777Recipient.json @@ -0,0 +1,49 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IERC777Recipient", + "sourceName": "contracts/interfaces/IERC777Recipient.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "userData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "operatorData", + "type": "bytes" + } + ], + "name": "tokensReceived", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC777Sender.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC777Sender.json new file mode 100644 index 00000000..4edd8a77 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC777Sender.json @@ -0,0 +1,49 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IERC777Sender", + "sourceName": "contracts/interfaces/IERC777Sender.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "userData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "operatorData", + "type": "bytes" + } + ], + "name": "tokensToSend", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC7802.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC7802.json new file mode 100644 index 00000000..5636f43b --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC7802.json @@ -0,0 +1,116 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IERC7802", + "sourceName": "contracts/interfaces/draft-IERC7802.sol", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "CrosschainBurn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "CrosschainMint", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "crosschainBurn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "crosschainMint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC7821.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC7821.json new file mode 100644 index 00000000..52d445c9 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC7821.json @@ -0,0 +1,48 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IERC7821", + "sourceName": "contracts/interfaces/draft-IERC7821.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "bytes32", + "name": "mode", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "executionData", + "type": "bytes" + } + ], + "name": "execute", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "mode", + "type": "bytes32" + } + ], + "name": "supportsExecutionMode", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC7913SignatureVerifier.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC7913SignatureVerifier.json new file mode 100644 index 00000000..8ae1eb53 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IERC7913SignatureVerifier.json @@ -0,0 +1,40 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IERC7913SignatureVerifier", + "sourceName": "contracts/interfaces/IERC7913.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "bytes", + "name": "key", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "verify", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IEntryPoint.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IEntryPoint.json new file mode 100644 index 00000000..4842a20f --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IEntryPoint.json @@ -0,0 +1,302 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IEntryPoint", + "sourceName": "contracts/interfaces/draft-IERC4337.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "uint256", + "name": "opIndex", + "type": "uint256" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "FailedOp", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "opIndex", + "type": "uint256" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "internalType": "bytes", + "name": "inner", + "type": "bytes" + } + ], + "name": "FailedOpWithRevert", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "unstakeDelaySec", + "type": "uint32" + } + ], + "name": "addStake", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "depositTo", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint192", + "name": "key", + "type": "uint192" + } + ], + "name": "getNonce", + "outputs": [ + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "components": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "initCode", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "callData", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "accountGasLimits", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "preVerificationGas", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "gasFees", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "paymasterAndData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "internalType": "struct PackedUserOperation[]", + "name": "userOps", + "type": "tuple[]" + }, + { + "internalType": "contract IAggregator", + "name": "aggregator", + "type": "address" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "internalType": "struct IEntryPoint.UserOpsPerAggregator[]", + "name": "opsPerAggregator", + "type": "tuple[]" + }, + { + "internalType": "address payable", + "name": "beneficiary", + "type": "address" + } + ], + "name": "handleAggregatedOps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "initCode", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "callData", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "accountGasLimits", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "preVerificationGas", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "gasFees", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "paymasterAndData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "internalType": "struct PackedUserOperation[]", + "name": "ops", + "type": "tuple[]" + }, + { + "internalType": "address payable", + "name": "beneficiary", + "type": "address" + } + ], + "name": "handleOps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "unlockStake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "withdrawAddress", + "type": "address" + } + ], + "name": "withdrawStake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "withdrawAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "withdrawAmount", + "type": "uint256" + } + ], + "name": "withdrawTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IEntryPointExtra.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IEntryPointExtra.json new file mode 100644 index 00000000..82b273ce --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IEntryPointExtra.json @@ -0,0 +1,77 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IEntryPointExtra", + "sourceName": "contracts/account/utils/draft-ERC4337Utils.sol", + "abi": [ + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "initCode", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "callData", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "accountGasLimits", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "preVerificationGas", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "gasFees", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "paymasterAndData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "internalType": "struct PackedUserOperation", + "name": "userOp", + "type": "tuple" + } + ], + "name": "getUserOpHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IEntryPointNonces.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IEntryPointNonces.json new file mode 100644 index 00000000..6a95c7e0 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IEntryPointNonces.json @@ -0,0 +1,35 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IEntryPointNonces", + "sourceName": "contracts/interfaces/draft-IERC4337.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint192", + "name": "key", + "type": "uint192" + } + ], + "name": "getNonce", + "outputs": [ + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IEntryPointStake.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IEntryPointStake.json new file mode 100644 index 00000000..13b3cdb1 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IEntryPointStake.json @@ -0,0 +1,94 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IEntryPointStake", + "sourceName": "contracts/interfaces/draft-IERC4337.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "uint32", + "name": "unstakeDelaySec", + "type": "uint32" + } + ], + "name": "addStake", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "depositTo", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "unlockStake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "withdrawAddress", + "type": "address" + } + ], + "name": "withdrawStake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "withdrawAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "withdrawAmount", + "type": "uint256" + } + ], + "name": "withdrawTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IGovernor.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IGovernor.json new file mode 100644 index 00000000..2cb39786 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IGovernor.json @@ -0,0 +1,1086 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IGovernor", + "sourceName": "contracts/governance/IGovernor.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "voter", + "type": "address" + } + ], + "name": "GovernorAlreadyCastVote", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorAlreadyQueuedProposal", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorDisabledDeposit", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "proposer", + "type": "address" + }, + { + "internalType": "uint256", + "name": "votes", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "threshold", + "type": "uint256" + } + ], + "name": "GovernorInsufficientProposerVotes", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "targets", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "calldatas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "values", + "type": "uint256" + } + ], + "name": "GovernorInvalidProposalLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "voter", + "type": "address" + } + ], + "name": "GovernorInvalidSignature", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorInvalidVoteParams", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorInvalidVoteType", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "votingPeriod", + "type": "uint256" + } + ], + "name": "GovernorInvalidVotingPeriod", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorNonexistentProposal", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "GovernorNotQueuedProposal", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "GovernorOnlyExecutor", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorQueueNotImplemented", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "proposer", + "type": "address" + } + ], + "name": "GovernorRestrictedProposer", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "GovernorUnableToCancel", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "enum IGovernor.ProposalState", + "name": "current", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "expectedStates", + "type": "bytes32" + } + ], + "name": "GovernorUnexpectedProposalState", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "ProposalCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "proposer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "string[]", + "name": "signatures", + "type": "string[]" + }, + { + "indexed": false, + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "voteStart", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "voteEnd", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "name": "ProposalCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "ProposalExecuted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "etaSeconds", + "type": "uint256" + } + ], + "name": "ProposalQueued", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "weight", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "VoteCast", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "weight", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "VoteCastWithParams", + "type": "event" + }, + { + "inputs": [], + "name": "CLOCK_MODE", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "COUNTING_MODE", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "cancel", + "outputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + } + ], + "name": "castVote", + "outputs": [ + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "castVoteBySig", + "outputs": [ + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "castVoteWithReason", + "outputs": [ + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "castVoteWithReasonAndParams", + "outputs": [ + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "castVoteWithReasonAndParamsBySig", + "outputs": [ + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "clock", + "outputs": [ + { + "internalType": "uint48", + "name": "", + "type": "uint48" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "execute", + "outputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "getProposalId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + } + ], + "name": "getVotes", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "getVotesWithParams", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasVoted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "hashProposal", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalDeadline", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalEta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalNeedsQueuing", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalProposer", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proposalThreshold", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "name": "propose", + "outputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "queue", + "outputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + } + ], + "name": "quorum", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "state", + "outputs": [ + { + "internalType": "enum IGovernor.ProposalState", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "votingDelay", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "votingPeriod", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IPaymaster.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IPaymaster.json new file mode 100644 index 00000000..b3d046ca --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IPaymaster.json @@ -0,0 +1,120 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IPaymaster", + "sourceName": "contracts/interfaces/draft-IERC4337.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "enum IPaymaster.PostOpMode", + "name": "mode", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "context", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "actualGasCost", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "actualUserOpFeePerGas", + "type": "uint256" + } + ], + "name": "postOp", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "initCode", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "callData", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "accountGasLimits", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "preVerificationGas", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "gasFees", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "paymasterAndData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "internalType": "struct PackedUserOperation", + "name": "userOp", + "type": "tuple" + }, + { + "internalType": "bytes32", + "name": "userOpHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "maxCost", + "type": "uint256" + } + ], + "name": "validatePaymasterUserOp", + "outputs": [ + { + "internalType": "bytes", + "name": "context", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "validationData", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ITransparentUpgradeableProxy.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ITransparentUpgradeableProxy.json new file mode 100644 index 00000000..a801a532 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ITransparentUpgradeableProxy.json @@ -0,0 +1,74 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ITransparentUpgradeableProxy", + "sourceName": "contracts/proxy/transparent/TransparentUpgradeableProxy.sol", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IVotes.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IVotes.json new file mode 100644 index 00000000..b721d260 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/IVotes.json @@ -0,0 +1,204 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IVotes", + "sourceName": "contracts/governance/utils/IVotes.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "uint256", + "name": "expiry", + "type": "uint256" + } + ], + "name": "VotesExpiredSignature", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "delegator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "fromDelegate", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "toDelegate", + "type": "address" + } + ], + "name": "DelegateChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "delegate", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "previousVotes", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newVotes", + "type": "uint256" + } + ], + "name": "DelegateVotesChanged", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "delegatee", + "type": "address" + } + ], + "name": "delegate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "delegatee", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "expiry", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "delegateBySig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "delegates", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + } + ], + "name": "getPastTotalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + } + ], + "name": "getPastVotes", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getVotes", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Initializable.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Initializable.json new file mode 100644 index 00000000..f08da888 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Initializable.json @@ -0,0 +1,34 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "Initializable", + "sourceName": "contracts/proxy/utils/Initializable.sol", + "abi": [ + { + "inputs": [], + "name": "InvalidInitialization", + "type": "error" + }, + { + "inputs": [], + "name": "NotInitializing", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "version", + "type": "uint64" + } + ], + "name": "Initialized", + "type": "event" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Math.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Math.json new file mode 100644 index 00000000..ae3b5a57 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Math.json @@ -0,0 +1,10 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "Math", + "sourceName": "contracts/utils/math/Math.sol", + "abi": [], + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220c24054a515b536168bbc774346cfbe7fe75bf736bc0cfa2fbe12ae625f4e354664736f6c634300081b0033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220c24054a515b536168bbc774346cfbe7fe75bf736bc0cfa2fbe12ae625f4e354664736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/MerkleProof.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/MerkleProof.json new file mode 100644 index 00000000..1c4fcdc2 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/MerkleProof.json @@ -0,0 +1,16 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "MerkleProof", + "sourceName": "contracts/utils/cryptography/MerkleProof.sol", + "abi": [ + { + "inputs": [], + "name": "MerkleProofInvalidMultiproof", + "type": "error" + } + ], + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220d1ce122d98b28b2410080eca30b264cbc114fab9c6cbad1353fd110c499357e464736f6c634300081b0033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220d1ce122d98b28b2410080eca30b264cbc114fab9c6cbad1353fd110c499357e464736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/MerkleTree.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/MerkleTree.json new file mode 100644 index 00000000..bd089b79 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/MerkleTree.json @@ -0,0 +1,32 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "MerkleTree", + "sourceName": "contracts/utils/structs/MerkleTree.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "length", + "type": "uint256" + } + ], + "name": "MerkleTreeUpdateInvalidIndex", + "type": "error" + }, + { + "inputs": [], + "name": "MerkleTreeUpdateInvalidProof", + "type": "error" + } + ], + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212202fc450c5e904dd178a603a417f4fc5838696b0bae01426625cbe6713c0652c2764736f6c634300081b0033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212202fc450c5e904dd178a603a417f4fc5838696b0bae01426625cbe6713c0652c2764736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/MessageHashUtils.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/MessageHashUtils.json new file mode 100644 index 00000000..e1a11ba9 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/MessageHashUtils.json @@ -0,0 +1,10 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "MessageHashUtils", + "sourceName": "contracts/utils/cryptography/MessageHashUtils.sol", + "abi": [], + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220484f002423a3dbfaa85eef59477f5b6b80392d92d9e15cccf9a15db3a001dcfc64736f6c634300081b0033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220484f002423a3dbfaa85eef59477f5b6b80392d92d9e15cccf9a15db3a001dcfc64736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/MultiSignerERC7913.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/MultiSignerERC7913.json new file mode 100644 index 00000000..59dc7c23 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/MultiSignerERC7913.json @@ -0,0 +1,173 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "MultiSignerERC7913", + "sourceName": "contracts/utils/cryptography/signers/MultiSignerERC7913.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "bytes", + "name": "signer", + "type": "bytes" + } + ], + "name": "MultiSignerERC7913AlreadyExists", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "signer", + "type": "bytes" + } + ], + "name": "MultiSignerERC7913InvalidSigner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "signer", + "type": "bytes" + } + ], + "name": "MultiSignerERC7913NonexistentSigner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "signers", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "threshold", + "type": "uint64" + } + ], + "name": "MultiSignerERC7913UnreachableThreshold", + "type": "error" + }, + { + "inputs": [], + "name": "MultiSignerERC7913ZeroThreshold", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes", + "name": "signers", + "type": "bytes" + } + ], + "name": "ERC7913SignerAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes", + "name": "signers", + "type": "bytes" + } + ], + "name": "ERC7913SignerRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "threshold", + "type": "uint64" + } + ], + "name": "ERC7913ThresholdSet", + "type": "event" + }, + { + "inputs": [], + "name": "getSignerCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "start", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "end", + "type": "uint64" + } + ], + "name": "getSigners", + "outputs": [ + { + "internalType": "bytes[]", + "name": "", + "type": "bytes[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "signer", + "type": "bytes" + } + ], + "name": "isSigner", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "threshold", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/MultiSignerERC7913Weighted.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/MultiSignerERC7913Weighted.json new file mode 100644 index 00000000..5443b4da --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/MultiSignerERC7913Weighted.json @@ -0,0 +1,261 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "MultiSignerERC7913Weighted", + "sourceName": "contracts/utils/cryptography/signers/MultiSignerERC7913Weighted.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "bytes", + "name": "signer", + "type": "bytes" + } + ], + "name": "MultiSignerERC7913AlreadyExists", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "signer", + "type": "bytes" + } + ], + "name": "MultiSignerERC7913InvalidSigner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "signer", + "type": "bytes" + } + ], + "name": "MultiSignerERC7913NonexistentSigner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "signers", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "threshold", + "type": "uint64" + } + ], + "name": "MultiSignerERC7913UnreachableThreshold", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "signer", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "weight", + "type": "uint64" + } + ], + "name": "MultiSignerERC7913WeightedInvalidWeight", + "type": "error" + }, + { + "inputs": [], + "name": "MultiSignerERC7913WeightedMismatchedLength", + "type": "error" + }, + { + "inputs": [], + "name": "MultiSignerERC7913ZeroThreshold", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "bits", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "SafeCastOverflowedUintDowncast", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes", + "name": "signers", + "type": "bytes" + } + ], + "name": "ERC7913SignerAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes", + "name": "signers", + "type": "bytes" + } + ], + "name": "ERC7913SignerRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes", + "name": "signer", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "weight", + "type": "uint64" + } + ], + "name": "ERC7913SignerWeightChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "threshold", + "type": "uint64" + } + ], + "name": "ERC7913ThresholdSet", + "type": "event" + }, + { + "inputs": [], + "name": "getSignerCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "start", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "end", + "type": "uint64" + } + ], + "name": "getSigners", + "outputs": [ + { + "internalType": "bytes[]", + "name": "", + "type": "bytes[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "signer", + "type": "bytes" + } + ], + "name": "isSigner", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "signer", + "type": "bytes" + } + ], + "name": "signerWeight", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "threshold", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalWeight", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Multicall.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Multicall.json new file mode 100644 index 00000000..2377d3eb --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Multicall.json @@ -0,0 +1,46 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "Multicall", + "sourceName": "contracts/utils/Multicall.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "AddressEmptyCode", + "type": "error" + }, + { + "inputs": [], + "name": "FailedCall", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "data", + "type": "bytes[]" + } + ], + "name": "multicall", + "outputs": [ + { + "internalType": "bytes[]", + "name": "results", + "type": "bytes[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Nonces.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Nonces.json new file mode 100644 index 00000000..a7c6280a --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Nonces.json @@ -0,0 +1,46 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "Nonces", + "sourceName": "contracts/utils/Nonces.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "currentNonce", + "type": "uint256" + } + ], + "name": "InvalidAccountNonce", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/NoncesKeyed.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/NoncesKeyed.json new file mode 100644 index 00000000..2a556702 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/NoncesKeyed.json @@ -0,0 +1,70 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "NoncesKeyed", + "sourceName": "contracts/utils/NoncesKeyed.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "currentNonce", + "type": "uint256" + } + ], + "name": "InvalidAccountNonce", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint192", + "name": "key", + "type": "uint192" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Ownable.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Ownable.json new file mode 100644 index 00000000..c8e73f73 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Ownable.json @@ -0,0 +1,85 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "Ownable", + "sourceName": "contracts/access/Ownable.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnableInvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "OwnableUnauthorizedAccount", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Ownable2Step.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Ownable2Step.json new file mode 100644 index 00000000..ab057311 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Ownable2Step.json @@ -0,0 +1,124 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "Ownable2Step", + "sourceName": "contracts/access/Ownable2Step.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnableInvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "OwnableUnauthorizedAccount", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferStarted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/P256.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/P256.json new file mode 100644 index 00000000..17479338 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/P256.json @@ -0,0 +1,10 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "P256", + "sourceName": "contracts/utils/cryptography/P256.sol", + "abi": [], + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220fa06b8ab196e95b687c9c39b94f18e6b694da00a4b22aef7472f3b54d8476ec064736f6c634300081b0033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220fa06b8ab196e95b687c9c39b94f18e6b694da00a4b22aef7472f3b54d8476ec064736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Packing.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Packing.json new file mode 100644 index 00000000..be73c616 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Packing.json @@ -0,0 +1,16 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "Packing", + "sourceName": "contracts/utils/Packing.sol", + "abi": [ + { + "inputs": [], + "name": "OutOfRangeAccess", + "type": "error" + } + ], + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220e62db5a2cc2140c16fc51476401f061d88202cb8c699e83d8ae5391e545b318064736f6c634300081b0033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220e62db5a2cc2140c16fc51476401f061d88202cb8c699e83d8ae5391e545b318064736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Panic.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Panic.json new file mode 100644 index 00000000..fee5e60f --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Panic.json @@ -0,0 +1,10 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "Panic", + "sourceName": "contracts/utils/Panic.sol", + "abi": [], + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212206caec39495ea6073a37d5399121744cac67d9c1c61c3b425451550b17d3e17ba64736f6c634300081b0033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212206caec39495ea6073a37d5399121744cac67d9c1c61c3b425451550b17d3e17ba64736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Pausable.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Pausable.json new file mode 100644 index 00000000..2c1205fc --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Pausable.json @@ -0,0 +1,60 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "Pausable", + "sourceName": "contracts/utils/Pausable.sol", + "abi": [ + { + "inputs": [], + "name": "EnforcedPause", + "type": "error" + }, + { + "inputs": [], + "name": "ExpectedPause", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Proxy.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Proxy.json new file mode 100644 index 00000000..947ef63b --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Proxy.json @@ -0,0 +1,15 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "Proxy", + "sourceName": "contracts/proxy/Proxy.sol", + "abi": [ + { + "stateMutability": "payable", + "type": "fallback" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ProxyAdmin.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ProxyAdmin.json new file mode 100644 index 00000000..6ec11d6f --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ProxyAdmin.json @@ -0,0 +1,132 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ProxyAdmin", + "sourceName": "contracts/proxy/transparent/ProxyAdmin.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "initialOwner", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnableInvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "OwnableUnauthorizedAccount", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "UPGRADE_INTERFACE_VERSION", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract ITransparentUpgradeableProxy", + "name": "proxy", + "type": "address" + }, + { + "internalType": "address", + "name": "implementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } + ], + "bytecode": "0x6080604052348015600e575f5ffd5b506040516104e63803806104e6833981016040819052602b9160b4565b806001600160a01b038116605857604051631e4fbdf760e01b81525f600482015260240160405180910390fd5b605f816065565b505060df565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b5f6020828403121560c3575f5ffd5b81516001600160a01b038116811460d8575f5ffd5b9392505050565b6103fa806100ec5f395ff3fe608060405260043610610049575f3560e01c8063715018a61461004d5780638da5cb5b146100635780639623609d1461008e578063ad3cb1cc146100a1578063f2fde38b146100de575b5f5ffd5b348015610058575f5ffd5b506100616100fd565b005b34801561006e575f5ffd5b505f546040516001600160a01b0390911681526020015b60405180910390f35b61006161009c366004610260565b610110565b3480156100ac575f5ffd5b506100d1604051806040016040528060058152602001640352e302e360dc1b81525081565b6040516100859190610365565b3480156100e9575f5ffd5b506100616100f836600461037e565b61017b565b6101056101bd565b61010e5f6101e9565b565b6101186101bd565b60405163278f794360e11b81526001600160a01b03841690634f1ef2869034906101489086908690600401610399565b5f604051808303818588803b15801561015f575f5ffd5b505af1158015610171573d5f5f3e3d5ffd5b5050505050505050565b6101836101bd565b6001600160a01b0381166101b157604051631e4fbdf760e01b81525f60048201526024015b60405180910390fd5b6101ba816101e9565b50565b5f546001600160a01b0316331461010e5760405163118cdaa760e01b81523360048201526024016101a8565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811681146101ba575f5ffd5b634e487b7160e01b5f52604160045260245ffd5b5f5f5f60608486031215610272575f5ffd5b833561027d81610238565b9250602084013561028d81610238565b9150604084013567ffffffffffffffff8111156102a8575f5ffd5b8401601f810186136102b8575f5ffd5b803567ffffffffffffffff8111156102d2576102d261024c565b604051601f8201601f19908116603f0116810167ffffffffffffffff811182821017156103015761030161024c565b604052818152828201602001881015610318575f5ffd5b816020840160208301375f602083830101528093505050509250925092565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f6103776020830184610337565b9392505050565b5f6020828403121561038e575f5ffd5b813561037781610238565b6001600160a01b03831681526040602082018190525f906103bc90830184610337565b94935050505056fea2646970667358221220787d2d426698dd68d81e8b7441ae3962906d711359b9b4f0d0836c9c0df5687564736f6c634300081b0033", + "deployedBytecode": "0x608060405260043610610049575f3560e01c8063715018a61461004d5780638da5cb5b146100635780639623609d1461008e578063ad3cb1cc146100a1578063f2fde38b146100de575b5f5ffd5b348015610058575f5ffd5b506100616100fd565b005b34801561006e575f5ffd5b505f546040516001600160a01b0390911681526020015b60405180910390f35b61006161009c366004610260565b610110565b3480156100ac575f5ffd5b506100d1604051806040016040528060058152602001640352e302e360dc1b81525081565b6040516100859190610365565b3480156100e9575f5ffd5b506100616100f836600461037e565b61017b565b6101056101bd565b61010e5f6101e9565b565b6101186101bd565b60405163278f794360e11b81526001600160a01b03841690634f1ef2869034906101489086908690600401610399565b5f604051808303818588803b15801561015f575f5ffd5b505af1158015610171573d5f5f3e3d5ffd5b5050505050505050565b6101836101bd565b6001600160a01b0381166101b157604051631e4fbdf760e01b81525f60048201526024015b60405180910390fd5b6101ba816101e9565b50565b5f546001600160a01b0316331461010e5760405163118cdaa760e01b81523360048201526024016101a8565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811681146101ba575f5ffd5b634e487b7160e01b5f52604160045260245ffd5b5f5f5f60608486031215610272575f5ffd5b833561027d81610238565b9250602084013561028d81610238565b9150604084013567ffffffffffffffff8111156102a8575f5ffd5b8401601f810186136102b8575f5ffd5b803567ffffffffffffffff8111156102d2576102d261024c565b604051601f8201601f19908116603f0116810167ffffffffffffffff811182821017156103015761030161024c565b604052818152828201602001881015610318575f5ffd5b816020840160208301375f602083830101528093505050509250925092565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f6103776020830184610337565b9392505050565b5f6020828403121561038e575f5ffd5b813561037781610238565b6001600160a01b03831681526040602082018190525f906103bc90830184610337565b94935050505056fea2646970667358221220787d2d426698dd68d81e8b7441ae3962906d711359b9b4f0d0836c9c0df5687564736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/RSA.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/RSA.json new file mode 100644 index 00000000..5e5950d0 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/RSA.json @@ -0,0 +1,10 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "RSA", + "sourceName": "contracts/utils/cryptography/RSA.sol", + "abi": [], + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220843ec8793e3085a3bd6d3861510d776a1562e5bd9c6c99b6d6bf7297cca5a9c864736f6c634300081b0033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220843ec8793e3085a3bd6d3861510d776a1562e5bd9c6c99b6d6bf7297cca5a9c864736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ReentrancyGuard.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ReentrancyGuard.json new file mode 100644 index 00000000..a4ca031d --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ReentrancyGuard.json @@ -0,0 +1,16 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ReentrancyGuard", + "sourceName": "contracts/utils/ReentrancyGuard.sol", + "abi": [ + { + "inputs": [], + "name": "ReentrancyGuardReentrantCall", + "type": "error" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ReentrancyGuardTransient.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ReentrancyGuardTransient.json new file mode 100644 index 00000000..f3288c42 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ReentrancyGuardTransient.json @@ -0,0 +1,16 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ReentrancyGuardTransient", + "sourceName": "contracts/utils/ReentrancyGuardTransient.sol", + "abi": [ + { + "inputs": [], + "name": "ReentrancyGuardReentrantCall", + "type": "error" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/SafeCast.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/SafeCast.json new file mode 100644 index 00000000..27a4487f --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/SafeCast.json @@ -0,0 +1,65 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "SafeCast", + "sourceName": "contracts/utils/math/SafeCast.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "uint8", + "name": "bits", + "type": "uint8" + }, + { + "internalType": "int256", + "name": "value", + "type": "int256" + } + ], + "name": "SafeCastOverflowedIntDowncast", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "value", + "type": "int256" + } + ], + "name": "SafeCastOverflowedIntToUint", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "bits", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "SafeCastOverflowedUintDowncast", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "SafeCastOverflowedUintToInt", + "type": "error" + } + ], + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220cdc0a6d6f1844696fe5e3590c11b6e01357d685363c24c8322eb82bed674804364736f6c634300081b0033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220cdc0a6d6f1844696fe5e3590c11b6e01357d685363c24c8322eb82bed674804364736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/SafeERC20.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/SafeERC20.json new file mode 100644 index 00000000..18809219 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/SafeERC20.json @@ -0,0 +1,43 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "SafeERC20", + "sourceName": "contracts/token/ERC20/utils/SafeERC20.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "currentAllowance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "requestedDecrease", + "type": "uint256" + } + ], + "name": "SafeERC20FailedDecreaseAllowance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "SafeERC20FailedOperation", + "type": "error" + } + ], + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220f14534f999eff3ff8188c7c5a10a94fee8b90a996c48faa2874c91fbc12036bd64736f6c634300081b0033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220f14534f999eff3ff8188c7c5a10a94fee8b90a996c48faa2874c91fbc12036bd64736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ShortStrings.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ShortStrings.json new file mode 100644 index 00000000..9b602ebc --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/ShortStrings.json @@ -0,0 +1,27 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ShortStrings", + "sourceName": "contracts/utils/ShortStrings.sol", + "abi": [ + { + "inputs": [], + "name": "InvalidShortString", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "str", + "type": "string" + } + ], + "name": "StringTooLong", + "type": "error" + } + ], + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220e031f63d8bdbc3a12ab6a5e8c79316f22e301d6402d7517faa8a3bfd041e90c764736f6c634300081b0033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220e031f63d8bdbc3a12ab6a5e8c79316f22e301d6402d7517faa8a3bfd041e90c764736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/SignatureChecker.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/SignatureChecker.json new file mode 100644 index 00000000..b498fb05 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/SignatureChecker.json @@ -0,0 +1,10 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "SignatureChecker", + "sourceName": "contracts/utils/cryptography/SignatureChecker.sol", + "abi": [], + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220552beef6b15a1c5fe981f7c1ac67513dd244c562564ae0a41a8b128cfac2efd264736f6c634300081b0033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220552beef6b15a1c5fe981f7c1ac67513dd244c562564ae0a41a8b128cfac2efd264736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/SignedMath.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/SignedMath.json new file mode 100644 index 00000000..49095ba0 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/SignedMath.json @@ -0,0 +1,10 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "SignedMath", + "sourceName": "contracts/utils/math/SignedMath.sol", + "abi": [], + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220b88d8d2710edc1e83c6bb4401e99631441b7a7f7894f6d46a3d8b8e0791b1acf64736f6c634300081b0033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220b88d8d2710edc1e83c6bb4401e99631441b7a7f7894f6d46a3d8b8e0791b1acf64736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/SignerECDSA.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/SignerECDSA.json new file mode 100644 index 00000000..a1ed938e --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/SignerECDSA.json @@ -0,0 +1,24 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "SignerECDSA", + "sourceName": "contracts/utils/cryptography/signers/SignerECDSA.sol", + "abi": [ + { + "inputs": [], + "name": "signer", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/SignerERC7702.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/SignerERC7702.json new file mode 100644 index 00000000..ea4f147d --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/SignerERC7702.json @@ -0,0 +1,10 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "SignerERC7702", + "sourceName": "contracts/utils/cryptography/signers/SignerERC7702.sol", + "abi": [], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/SignerERC7913.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/SignerERC7913.json new file mode 100644 index 00000000..bb33426c --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/SignerERC7913.json @@ -0,0 +1,24 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "SignerERC7913", + "sourceName": "contracts/utils/cryptography/signers/SignerERC7913.sol", + "abi": [ + { + "inputs": [], + "name": "signer", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/SignerP256.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/SignerP256.json new file mode 100644 index 00000000..a3b7962e --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/SignerP256.json @@ -0,0 +1,45 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "SignerP256", + "sourceName": "contracts/utils/cryptography/signers/SignerP256.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "bytes32", + "name": "qx", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "qy", + "type": "bytes32" + } + ], + "name": "SignerP256InvalidPublicKey", + "type": "error" + }, + { + "inputs": [], + "name": "signer", + "outputs": [ + { + "internalType": "bytes32", + "name": "qx", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "qy", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/SignerRSA.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/SignerRSA.json new file mode 100644 index 00000000..876899e3 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/SignerRSA.json @@ -0,0 +1,29 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "SignerRSA", + "sourceName": "contracts/utils/cryptography/signers/SignerRSA.sol", + "abi": [ + { + "inputs": [], + "name": "signer", + "outputs": [ + { + "internalType": "bytes", + "name": "e", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "n", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/SlotDerivation.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/SlotDerivation.json new file mode 100644 index 00000000..361ec5b3 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/SlotDerivation.json @@ -0,0 +1,10 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "SlotDerivation", + "sourceName": "contracts/utils/SlotDerivation.sol", + "abi": [], + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122051f88f3f17819814eef65004799ed66f4fe8589a9471eeaa628d93ae4ebfbd3264736f6c634300081b0033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122051f88f3f17819814eef65004799ed66f4fe8589a9471eeaa628d93ae4ebfbd3264736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/StorageSlot.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/StorageSlot.json new file mode 100644 index 00000000..d9f83cdb --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/StorageSlot.json @@ -0,0 +1,10 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "StorageSlot", + "sourceName": "contracts/utils/StorageSlot.sol", + "abi": [], + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212200d83593a1d7d29bd8ee1c3bd9b728524fc750d1c9bedc1a23f3d73b8940f181364736f6c634300081b0033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea26469706673582212200d83593a1d7d29bd8ee1c3bd9b728524fc750d1c9bedc1a23f3d73b8940f181364736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Strings.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Strings.json new file mode 100644 index 00000000..019622d0 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Strings.json @@ -0,0 +1,37 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "Strings", + "sourceName": "contracts/utils/Strings.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "length", + "type": "uint256" + } + ], + "name": "StringsInsufficientHexLength", + "type": "error" + }, + { + "inputs": [], + "name": "StringsInvalidAddressFormat", + "type": "error" + }, + { + "inputs": [], + "name": "StringsInvalidChar", + "type": "error" + } + ], + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220286809d48abee4169d5b03cd5b9c06455a85650a0ee12351da7c4f6b613a395264736f6c634300081b0033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220286809d48abee4169d5b03cd5b9c06455a85650a0ee12351da7c4f6b613a395264736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Time.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Time.json new file mode 100644 index 00000000..fe271334 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Time.json @@ -0,0 +1,10 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "Time", + "sourceName": "contracts/utils/types/Time.sol", + "abi": [], + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220d4b5b8b1f54517aa1236b04b785899fd576da738fcf1190dc1981f14a097e41864736f6c634300081b0033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220d4b5b8b1f54517aa1236b04b785899fd576da738fcf1190dc1981f14a097e41864736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/TimelockController.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/TimelockController.json new file mode 100644 index 00000000..13e5880a --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/TimelockController.json @@ -0,0 +1,1007 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "TimelockController", + "sourceName": "contracts/governance/TimelockController.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "uint256", + "name": "minDelay", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "proposers", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "executors", + "type": "address[]" + }, + { + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "AccessControlBadConfirmation", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "neededRole", + "type": "bytes32" + } + ], + "name": "AccessControlUnauthorizedAccount", + "type": "error" + }, + { + "inputs": [], + "name": "FailedCall", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "delay", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minDelay", + "type": "uint256" + } + ], + "name": "TimelockInsufficientDelay", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "targets", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "payloads", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "values", + "type": "uint256" + } + ], + "name": "TimelockInvalidOperationLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "caller", + "type": "address" + } + ], + "name": "TimelockUnauthorizedCaller", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "predecessorId", + "type": "bytes32" + } + ], + "name": "TimelockUnexecutedPredecessor", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "operationId", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "expectedStates", + "type": "bytes32" + } + ], + "name": "TimelockUnexpectedOperationState", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "index", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "CallExecuted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + } + ], + "name": "CallSalt", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "index", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "predecessor", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "delay", + "type": "uint256" + } + ], + "name": "CallScheduled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "Cancelled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldDuration", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newDuration", + "type": "uint256" + } + ], + "name": "MinDelayChange", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "inputs": [], + "name": "CANCELLER_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "EXECUTOR_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PROPOSER_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "cancel", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "payload", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "predecessor", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + } + ], + "name": "execute", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "payloads", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "predecessor", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + } + ], + "name": "executeBatch", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "getMinDelay", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "getOperationState", + "outputs": [ + { + "internalType": "enum TimelockController.OperationState", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "getTimestamp", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "predecessor", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + } + ], + "name": "hashOperation", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "payloads", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "predecessor", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + } + ], + "name": "hashOperationBatch", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "isOperation", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "isOperationDone", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "isOperationPending", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "isOperationReady", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC1155BatchReceived", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC1155Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC721Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "callerConfirmation", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "predecessor", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "delay", + "type": "uint256" + } + ], + "name": "schedule", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "payloads", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "predecessor", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "delay", + "type": "uint256" + } + ], + "name": "scheduleBatch", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newDelay", + "type": "uint256" + } + ], + "name": "updateDelay", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "bytecode": "0x608060405234801561000f575f5ffd5b50604051611d2b380380611d2b83398101604081905261002e916102f6565b6100385f3061017b565b506001600160a01b03811615610054576100525f8261017b565b505b5f5b83518110156100e8576100a87fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc185838151811061009557610095610375565b602002602001015161017b60201b60201c565b506100df7ffd643c72710c63c0180259aba6b2d05451e3591a24e58b62239378085726f78385838151811061009557610095610375565b50600101610056565b505f5b82518110156101335761012a7fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e6384838151811061009557610095610375565b506001016100eb565b506002849055604080515f8152602081018690527f11c24f4ead16507c69ac467fbd5e4eed5fb5c699626d2cc6d66421df253886d5910160405180910390a150505050610389565b5f828152602081815260408083206001600160a01b038516845290915281205460ff1661021b575f838152602081815260408083206001600160a01b03861684529091529020805460ff191660011790556101d33390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a450600161021e565b505f5b92915050565b634e487b7160e01b5f52604160045260245ffd5b80516001600160a01b038116811461024e575f5ffd5b919050565b5f82601f830112610262575f5ffd5b81516001600160401b0381111561027b5761027b610224565b604051600582901b90603f8201601f191681016001600160401b03811182821017156102a9576102a9610224565b6040529182526020818501810192908101868411156102c6575f5ffd5b6020860192505b838310156102ec576102de83610238565b8152602092830192016102cd565b5095945050505050565b5f5f5f5f60808587031215610309575f5ffd5b845160208601519094506001600160401b03811115610326575f5ffd5b61033287828801610253565b604087015190945090506001600160401b0381111561034f575f5ffd5b61035b87828801610253565b92505061036a60608601610238565b905092959194509250565b634e487b7160e01b5f52603260045260245ffd5b611995806103965f395ff3fe6080604052600436106101b2575f3560e01c80638065657f116100e7578063bc197c8111610087578063d547741f11610062578063d547741f14610546578063e38335e514610565578063f23a6e6114610578578063f27a0c92146105a3575f5ffd5b8063bc197c81146104d1578063c4d252f5146104fc578063d45c44351461051b575f5ffd5b806391d14854116100c257806391d148541461044d578063a217fddf1461046c578063b08e51c01461047f578063b1c5f427146104b2575f5ffd5b80638065657f146103dc5780638f2a0bb0146103fb5780638f61f4f51461041a575f5ffd5b80632ab0f5291161015257806336568abe1161012d57806336568abe14610353578063584b153e1461037257806364d62353146103915780637958004c146103b0575f5ffd5b80632ab0f529146102f65780632f2ff15d1461031557806331d5075014610334575f5ffd5b8063134008d31161018d578063134008d31461025357806313bc9f2014610266578063150b7a0214610285578063248a9ca3146102c8575f5ffd5b806301d5062a146101bd57806301ffc9a7146101de57806307bd026514610212575f5ffd5b366101b957005b5f5ffd5b3480156101c8575f5ffd5b506101dc6101d7366004611162565b6105b7565b005b3480156101e9575f5ffd5b506101fd6101f83660046111d0565b61068b565b60405190151581526020015b60405180910390f35b34801561021d575f5ffd5b506102457fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e6381565b604051908152602001610209565b6101dc6102613660046111f7565b61069b565b348015610271575f5ffd5b506101fd61028036600461125d565b61074d565b348015610290575f5ffd5b506102af61029f366004611323565b630a85bd0160e11b949350505050565b6040516001600160e01b03199091168152602001610209565b3480156102d3575f5ffd5b506102456102e236600461125d565b5f9081526020819052604090206001015490565b348015610301575f5ffd5b506101fd61031036600461125d565b610772565b348015610320575f5ffd5b506101dc61032f366004611386565b61077a565b34801561033f575f5ffd5b506101fd61034e36600461125d565b6107a4565b34801561035e575f5ffd5b506101dc61036d366004611386565b6107c8565b34801561037d575f5ffd5b506101fd61038c36600461125d565b610800565b34801561039c575f5ffd5b506101dc6103ab36600461125d565b610845565b3480156103bb575f5ffd5b506103cf6103ca36600461125d565b6108b8565b60405161020991906113c4565b3480156103e7575f5ffd5b506102456103f63660046111f7565b610900565b348015610406575f5ffd5b506101dc61041536600461142a565b61093e565b348015610425575f5ffd5b506102457fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc181565b348015610458575f5ffd5b506101fd610467366004611386565b610aca565b348015610477575f5ffd5b506102455f81565b34801561048a575f5ffd5b506102457ffd643c72710c63c0180259aba6b2d05451e3591a24e58b62239378085726f78381565b3480156104bd575f5ffd5b506102456104cc3660046114dc565b610af2565b3480156104dc575f5ffd5b506102af6104eb366004611605565b63bc197c8160e01b95945050505050565b348015610507575f5ffd5b506101dc61051636600461125d565b610b36565b348015610526575f5ffd5b5061024561053536600461125d565b5f9081526001602052604090205490565b348015610551575f5ffd5b506101dc610560366004611386565b610be0565b6101dc6105733660046114dc565b610c04565b348015610583575f5ffd5b506102af6105923660046116b1565b63f23a6e6160e01b95945050505050565b3480156105ae575f5ffd5b50600254610245565b7fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc16105e181610d85565b5f6105f0898989898989610900565b90506105fc8184610d92565b5f817f4cf4410cc57040e44862ef0f45f3dd5a5e02db8eb8add648d4b0e236f1d07dca8b8b8b8b8b8a6040516106379695949392919061172c565b60405180910390a3831561068057807f20fda5fd27a1ea7bf5b9567f143ac5470bb059374a27e8f67cb44f946f6d03878560405161067791815260200190565b60405180910390a25b505050505050505050565b5f61069582610e23565b92915050565b7fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e636106c6815f610aca565b6106d4576106d48133610e47565b5f6106e3888888888888610900565b90506106ef8185610e84565b6106fb88888888610ed2565b5f817fc2617efa69bab66782fa219543714338489c4e9e178271560a91b82c3f612b588a8a8a8a6040516107329493929190611768565b60405180910390a361074381610f46565b5050505050505050565b5f60025b61075a836108b8565b600381111561076b5761076b6113b0565b1492915050565b5f6003610751565b5f8281526020819052604090206001015461079481610d85565b61079e8383610f71565b50505050565b5f806107af836108b8565b60038111156107c0576107c06113b0565b141592915050565b6001600160a01b03811633146107f15760405163334bd91960e11b815260040160405180910390fd5b6107fb8282611000565b505050565b5f5f61080b836108b8565b90506001816003811115610821576108216113b0565b148061083e5750600281600381111561083c5761083c6113b0565b145b9392505050565b333081146108765760405163e2850c5960e01b81526001600160a01b03821660048201526024015b60405180910390fd5b60025460408051918252602082018490527f11c24f4ead16507c69ac467fbd5e4eed5fb5c699626d2cc6d66421df253886d5910160405180910390a150600255565b5f81815260016020526040812054805f036108d557505f92915050565b600181036108e65750600392915050565b428111156108f75750600192915050565b50600292915050565b5f86868686868660405160200161091c9695949392919061172c565b6040516020818303038152906040528051906020012090509695505050505050565b7fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc161096881610d85565b88871415806109775750888514155b156109a9576040516001624fcdef60e01b03198152600481018a9052602481018690526044810188905260640161086d565b5f6109ba8b8b8b8b8b8b8b8b610af2565b90506109c68184610d92565b5f5b8a811015610a7b5780827f4cf4410cc57040e44862ef0f45f3dd5a5e02db8eb8add648d4b0e236f1d07dca8e8e85818110610a0557610a0561178f565b9050602002016020810190610a1a91906117a3565b8d8d86818110610a2c57610a2c61178f565b905060200201358c8c87818110610a4557610a4561178f565b9050602002810190610a5791906117bc565b8c8b604051610a6b9695949392919061172c565b60405180910390a36001016109c8565b508315610abd57807f20fda5fd27a1ea7bf5b9567f143ac5470bb059374a27e8f67cb44f946f6d038785604051610ab491815260200190565b60405180910390a25b5050505050505050505050565b5f918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b5f8888888888888888604051602001610b12989796959493929190611892565b60405160208183030381529060405280519060200120905098975050505050505050565b7ffd643c72710c63c0180259aba6b2d05451e3591a24e58b62239378085726f783610b6081610d85565b610b6982610800565b610ba55781610b786002611069565b610b826001611069565b604051635ead8eb560e01b8152600481019390935217602482015260440161086d565b5f828152600160205260408082208290555183917fbaa1eb22f2a492ba1a5fea61b8df4d27c6c8b5f3971e63bb58fa14ff72eedb7091a25050565b5f82815260208190526040902060010154610bfa81610d85565b61079e8383611000565b7fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e63610c2f815f610aca565b610c3d57610c3d8133610e47565b8786141580610c4c5750878414155b15610c7e576040516001624fcdef60e01b0319815260048101899052602481018590526044810187905260640161086d565b5f610c8f8a8a8a8a8a8a8a8a610af2565b9050610c9b8185610e84565b5f5b89811015610d6f575f8b8b83818110610cb857610cb861178f565b9050602002016020810190610ccd91906117a3565b90505f8a8a84818110610ce257610ce261178f565b905060200201359050365f8a8a86818110610cff57610cff61178f565b9050602002810190610d1191906117bc565b91509150610d2184848484610ed2565b84867fc2617efa69bab66782fa219543714338489c4e9e178271560a91b82c3f612b5886868686604051610d589493929190611768565b60405180910390a350505050806001019050610c9d565b50610d7981610f46565b50505050505050505050565b610d8f8133610e47565b50565b610d9b826107a4565b15610dcc5781610daa5f611069565b604051635ead8eb560e01b81526004810192909252602482015260440161086d565b5f610dd660025490565b905080821015610e0357604051635433660960e01b8152600481018390526024810182905260440161086d565b610e0d8242611931565b5f93845260016020526040909320929092555050565b5f6001600160e01b03198216630271189760e51b148061069557506106958261108b565b610e518282610aca565b610e805760405163e2517d3f60e01b81526001600160a01b03821660048201526024810183905260440161086d565b5050565b610e8d8261074d565b610e9c5781610daa6002611069565b8015801590610eb15750610eaf81610772565b155b15610e805760405163121534c360e31b81526004810182905260240161086d565b5f5f856001600160a01b0316858585604051610eef929190611950565b5f6040518083038185875af1925050503d805f8114610f29576040519150601f19603f3d011682016040523d82523d5f602084013e610f2e565b606091505b5091509150610f3d82826110bf565b50505050505050565b610f4f8161074d565b610f5e5780610daa6002611069565b5f90815260016020819052604090912055565b5f610f7c8383610aca565b610ff9575f838152602081815260408083206001600160a01b03861684529091529020805460ff19166001179055610fb13390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001610695565b505f610695565b5f61100b8383610aca565b15610ff9575f838152602081815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a4506001610695565b5f81600381111561107c5761107c6113b0565b600160ff919091161b92915050565b5f6001600160e01b03198216637965db0b60e01b148061069557506301ffc9a760e01b6001600160e01b0319831614610695565b6060826110d4576110cf826110db565b610695565b5080610695565b8051156110ea57805160208201fd5b60405163d6bda27560e01b815260040160405180910390fd5b80356001600160a01b0381168114611119575f5ffd5b919050565b5f5f83601f84011261112e575f5ffd5b5081356001600160401b03811115611144575f5ffd5b60208301915083602082850101111561115b575f5ffd5b9250929050565b5f5f5f5f5f5f5f60c0888a031215611178575f5ffd5b61118188611103565b96506020880135955060408801356001600160401b038111156111a2575f5ffd5b6111ae8a828b0161111e565b989b979a50986060810135976080820135975060a09091013595509350505050565b5f602082840312156111e0575f5ffd5b81356001600160e01b03198116811461083e575f5ffd5b5f5f5f5f5f5f60a0878903121561120c575f5ffd5b61121587611103565b95506020870135945060408701356001600160401b03811115611236575f5ffd5b61124289828a0161111e565b979a9699509760608101359660809091013595509350505050565b5f6020828403121561126d575f5ffd5b5035919050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f191681016001600160401b03811182821017156112b0576112b0611274565b604052919050565b5f82601f8301126112c7575f5ffd5b81356001600160401b038111156112e0576112e0611274565b6112f3601f8201601f1916602001611288565b818152846020838601011115611307575f5ffd5b816020850160208301375f918101602001919091529392505050565b5f5f5f5f60808587031215611336575f5ffd5b61133f85611103565b935061134d60208601611103565b92506040850135915060608501356001600160401b0381111561136e575f5ffd5b61137a878288016112b8565b91505092959194509250565b5f5f60408385031215611397575f5ffd5b823591506113a760208401611103565b90509250929050565b634e487b7160e01b5f52602160045260245ffd5b60208101600483106113e457634e487b7160e01b5f52602160045260245ffd5b91905290565b5f5f83601f8401126113fa575f5ffd5b5081356001600160401b03811115611410575f5ffd5b6020830191508360208260051b850101111561115b575f5ffd5b5f5f5f5f5f5f5f5f5f60c08a8c031215611442575f5ffd5b89356001600160401b03811115611457575f5ffd5b6114638c828d016113ea565b909a5098505060208a01356001600160401b03811115611481575f5ffd5b61148d8c828d016113ea565b90985096505060408a01356001600160401b038111156114ab575f5ffd5b6114b78c828d016113ea565b9a9d999c50979a969997986060880135976080810135975060a0013595509350505050565b5f5f5f5f5f5f5f5f60a0898b0312156114f3575f5ffd5b88356001600160401b03811115611508575f5ffd5b6115148b828c016113ea565b90995097505060208901356001600160401b03811115611532575f5ffd5b61153e8b828c016113ea565b90975095505060408901356001600160401b0381111561155c575f5ffd5b6115688b828c016113ea565b999c989b509699959896976060870135966080013595509350505050565b5f82601f830112611595575f5ffd5b81356001600160401b038111156115ae576115ae611274565b8060051b6115be60208201611288565b918252602081850181019290810190868411156115d9575f5ffd5b6020860192505b838310156115fb5782358252602092830192909101906115e0565b9695505050505050565b5f5f5f5f5f60a08688031215611619575f5ffd5b61162286611103565b945061163060208701611103565b935060408601356001600160401b0381111561164a575f5ffd5b61165688828901611586565b93505060608601356001600160401b03811115611671575f5ffd5b61167d88828901611586565b92505060808601356001600160401b03811115611698575f5ffd5b6116a4888289016112b8565b9150509295509295909350565b5f5f5f5f5f60a086880312156116c5575f5ffd5b6116ce86611103565b94506116dc60208701611103565b9350604086013592506060860135915060808601356001600160401b03811115611698575f5ffd5b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b60018060a01b038716815285602082015260a060408201525f61175360a083018688611704565b60608301949094525060800152949350505050565b60018060a01b0385168152836020820152606060408201525f6115fb606083018486611704565b634e487b7160e01b5f52603260045260245ffd5b5f602082840312156117b3575f5ffd5b61083e82611103565b5f5f8335601e198436030181126117d1575f5ffd5b8301803591506001600160401b038211156117ea575f5ffd5b60200191503681900382131561115b575f5ffd5b5f8383855260208501945060208460051b820101835f5b8681101561188657838303601f19018852813536879003601e1901811261183a575f5ffd5b86016020810190356001600160401b03811115611855575f5ffd5b803603821315611863575f5ffd5b61186e858284611704565b60209a8b019a90955093909301925050600101611815565b50909695505050505050565b60a080825281018890525f8960c08301825b8b8110156118d2576001600160a01b036118bd84611103565b168252602092830192909101906001016118a4565b5083810360208501528881526001600160fb1b038911156118f1575f5ffd5b8860051b9150818a6020830137018281036020908101604085015261191990820187896117fe565b60608401959095525050608001529695505050505050565b8082018082111561069557634e487b7160e01b5f52601160045260245ffd5b818382375f910190815291905056fea2646970667358221220e6173ba0cadc9786932aa5be7c9644d0283de2cf799db818e672801f0259da7264736f6c634300081b0033", + "deployedBytecode": "0x6080604052600436106101b2575f3560e01c80638065657f116100e7578063bc197c8111610087578063d547741f11610062578063d547741f14610546578063e38335e514610565578063f23a6e6114610578578063f27a0c92146105a3575f5ffd5b8063bc197c81146104d1578063c4d252f5146104fc578063d45c44351461051b575f5ffd5b806391d14854116100c257806391d148541461044d578063a217fddf1461046c578063b08e51c01461047f578063b1c5f427146104b2575f5ffd5b80638065657f146103dc5780638f2a0bb0146103fb5780638f61f4f51461041a575f5ffd5b80632ab0f5291161015257806336568abe1161012d57806336568abe14610353578063584b153e1461037257806364d62353146103915780637958004c146103b0575f5ffd5b80632ab0f529146102f65780632f2ff15d1461031557806331d5075014610334575f5ffd5b8063134008d31161018d578063134008d31461025357806313bc9f2014610266578063150b7a0214610285578063248a9ca3146102c8575f5ffd5b806301d5062a146101bd57806301ffc9a7146101de57806307bd026514610212575f5ffd5b366101b957005b5f5ffd5b3480156101c8575f5ffd5b506101dc6101d7366004611162565b6105b7565b005b3480156101e9575f5ffd5b506101fd6101f83660046111d0565b61068b565b60405190151581526020015b60405180910390f35b34801561021d575f5ffd5b506102457fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e6381565b604051908152602001610209565b6101dc6102613660046111f7565b61069b565b348015610271575f5ffd5b506101fd61028036600461125d565b61074d565b348015610290575f5ffd5b506102af61029f366004611323565b630a85bd0160e11b949350505050565b6040516001600160e01b03199091168152602001610209565b3480156102d3575f5ffd5b506102456102e236600461125d565b5f9081526020819052604090206001015490565b348015610301575f5ffd5b506101fd61031036600461125d565b610772565b348015610320575f5ffd5b506101dc61032f366004611386565b61077a565b34801561033f575f5ffd5b506101fd61034e36600461125d565b6107a4565b34801561035e575f5ffd5b506101dc61036d366004611386565b6107c8565b34801561037d575f5ffd5b506101fd61038c36600461125d565b610800565b34801561039c575f5ffd5b506101dc6103ab36600461125d565b610845565b3480156103bb575f5ffd5b506103cf6103ca36600461125d565b6108b8565b60405161020991906113c4565b3480156103e7575f5ffd5b506102456103f63660046111f7565b610900565b348015610406575f5ffd5b506101dc61041536600461142a565b61093e565b348015610425575f5ffd5b506102457fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc181565b348015610458575f5ffd5b506101fd610467366004611386565b610aca565b348015610477575f5ffd5b506102455f81565b34801561048a575f5ffd5b506102457ffd643c72710c63c0180259aba6b2d05451e3591a24e58b62239378085726f78381565b3480156104bd575f5ffd5b506102456104cc3660046114dc565b610af2565b3480156104dc575f5ffd5b506102af6104eb366004611605565b63bc197c8160e01b95945050505050565b348015610507575f5ffd5b506101dc61051636600461125d565b610b36565b348015610526575f5ffd5b5061024561053536600461125d565b5f9081526001602052604090205490565b348015610551575f5ffd5b506101dc610560366004611386565b610be0565b6101dc6105733660046114dc565b610c04565b348015610583575f5ffd5b506102af6105923660046116b1565b63f23a6e6160e01b95945050505050565b3480156105ae575f5ffd5b50600254610245565b7fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc16105e181610d85565b5f6105f0898989898989610900565b90506105fc8184610d92565b5f817f4cf4410cc57040e44862ef0f45f3dd5a5e02db8eb8add648d4b0e236f1d07dca8b8b8b8b8b8a6040516106379695949392919061172c565b60405180910390a3831561068057807f20fda5fd27a1ea7bf5b9567f143ac5470bb059374a27e8f67cb44f946f6d03878560405161067791815260200190565b60405180910390a25b505050505050505050565b5f61069582610e23565b92915050565b7fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e636106c6815f610aca565b6106d4576106d48133610e47565b5f6106e3888888888888610900565b90506106ef8185610e84565b6106fb88888888610ed2565b5f817fc2617efa69bab66782fa219543714338489c4e9e178271560a91b82c3f612b588a8a8a8a6040516107329493929190611768565b60405180910390a361074381610f46565b5050505050505050565b5f60025b61075a836108b8565b600381111561076b5761076b6113b0565b1492915050565b5f6003610751565b5f8281526020819052604090206001015461079481610d85565b61079e8383610f71565b50505050565b5f806107af836108b8565b60038111156107c0576107c06113b0565b141592915050565b6001600160a01b03811633146107f15760405163334bd91960e11b815260040160405180910390fd5b6107fb8282611000565b505050565b5f5f61080b836108b8565b90506001816003811115610821576108216113b0565b148061083e5750600281600381111561083c5761083c6113b0565b145b9392505050565b333081146108765760405163e2850c5960e01b81526001600160a01b03821660048201526024015b60405180910390fd5b60025460408051918252602082018490527f11c24f4ead16507c69ac467fbd5e4eed5fb5c699626d2cc6d66421df253886d5910160405180910390a150600255565b5f81815260016020526040812054805f036108d557505f92915050565b600181036108e65750600392915050565b428111156108f75750600192915050565b50600292915050565b5f86868686868660405160200161091c9695949392919061172c565b6040516020818303038152906040528051906020012090509695505050505050565b7fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc161096881610d85565b88871415806109775750888514155b156109a9576040516001624fcdef60e01b03198152600481018a9052602481018690526044810188905260640161086d565b5f6109ba8b8b8b8b8b8b8b8b610af2565b90506109c68184610d92565b5f5b8a811015610a7b5780827f4cf4410cc57040e44862ef0f45f3dd5a5e02db8eb8add648d4b0e236f1d07dca8e8e85818110610a0557610a0561178f565b9050602002016020810190610a1a91906117a3565b8d8d86818110610a2c57610a2c61178f565b905060200201358c8c87818110610a4557610a4561178f565b9050602002810190610a5791906117bc565b8c8b604051610a6b9695949392919061172c565b60405180910390a36001016109c8565b508315610abd57807f20fda5fd27a1ea7bf5b9567f143ac5470bb059374a27e8f67cb44f946f6d038785604051610ab491815260200190565b60405180910390a25b5050505050505050505050565b5f918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b5f8888888888888888604051602001610b12989796959493929190611892565b60405160208183030381529060405280519060200120905098975050505050505050565b7ffd643c72710c63c0180259aba6b2d05451e3591a24e58b62239378085726f783610b6081610d85565b610b6982610800565b610ba55781610b786002611069565b610b826001611069565b604051635ead8eb560e01b8152600481019390935217602482015260440161086d565b5f828152600160205260408082208290555183917fbaa1eb22f2a492ba1a5fea61b8df4d27c6c8b5f3971e63bb58fa14ff72eedb7091a25050565b5f82815260208190526040902060010154610bfa81610d85565b61079e8383611000565b7fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e63610c2f815f610aca565b610c3d57610c3d8133610e47565b8786141580610c4c5750878414155b15610c7e576040516001624fcdef60e01b0319815260048101899052602481018590526044810187905260640161086d565b5f610c8f8a8a8a8a8a8a8a8a610af2565b9050610c9b8185610e84565b5f5b89811015610d6f575f8b8b83818110610cb857610cb861178f565b9050602002016020810190610ccd91906117a3565b90505f8a8a84818110610ce257610ce261178f565b905060200201359050365f8a8a86818110610cff57610cff61178f565b9050602002810190610d1191906117bc565b91509150610d2184848484610ed2565b84867fc2617efa69bab66782fa219543714338489c4e9e178271560a91b82c3f612b5886868686604051610d589493929190611768565b60405180910390a350505050806001019050610c9d565b50610d7981610f46565b50505050505050505050565b610d8f8133610e47565b50565b610d9b826107a4565b15610dcc5781610daa5f611069565b604051635ead8eb560e01b81526004810192909252602482015260440161086d565b5f610dd660025490565b905080821015610e0357604051635433660960e01b8152600481018390526024810182905260440161086d565b610e0d8242611931565b5f93845260016020526040909320929092555050565b5f6001600160e01b03198216630271189760e51b148061069557506106958261108b565b610e518282610aca565b610e805760405163e2517d3f60e01b81526001600160a01b03821660048201526024810183905260440161086d565b5050565b610e8d8261074d565b610e9c5781610daa6002611069565b8015801590610eb15750610eaf81610772565b155b15610e805760405163121534c360e31b81526004810182905260240161086d565b5f5f856001600160a01b0316858585604051610eef929190611950565b5f6040518083038185875af1925050503d805f8114610f29576040519150601f19603f3d011682016040523d82523d5f602084013e610f2e565b606091505b5091509150610f3d82826110bf565b50505050505050565b610f4f8161074d565b610f5e5780610daa6002611069565b5f90815260016020819052604090912055565b5f610f7c8383610aca565b610ff9575f838152602081815260408083206001600160a01b03861684529091529020805460ff19166001179055610fb13390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001610695565b505f610695565b5f61100b8383610aca565b15610ff9575f838152602081815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a4506001610695565b5f81600381111561107c5761107c6113b0565b600160ff919091161b92915050565b5f6001600160e01b03198216637965db0b60e01b148061069557506301ffc9a760e01b6001600160e01b0319831614610695565b6060826110d4576110cf826110db565b610695565b5080610695565b8051156110ea57805160208201fd5b60405163d6bda27560e01b815260040160405180910390fd5b80356001600160a01b0381168114611119575f5ffd5b919050565b5f5f83601f84011261112e575f5ffd5b5081356001600160401b03811115611144575f5ffd5b60208301915083602082850101111561115b575f5ffd5b9250929050565b5f5f5f5f5f5f5f60c0888a031215611178575f5ffd5b61118188611103565b96506020880135955060408801356001600160401b038111156111a2575f5ffd5b6111ae8a828b0161111e565b989b979a50986060810135976080820135975060a09091013595509350505050565b5f602082840312156111e0575f5ffd5b81356001600160e01b03198116811461083e575f5ffd5b5f5f5f5f5f5f60a0878903121561120c575f5ffd5b61121587611103565b95506020870135945060408701356001600160401b03811115611236575f5ffd5b61124289828a0161111e565b979a9699509760608101359660809091013595509350505050565b5f6020828403121561126d575f5ffd5b5035919050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f191681016001600160401b03811182821017156112b0576112b0611274565b604052919050565b5f82601f8301126112c7575f5ffd5b81356001600160401b038111156112e0576112e0611274565b6112f3601f8201601f1916602001611288565b818152846020838601011115611307575f5ffd5b816020850160208301375f918101602001919091529392505050565b5f5f5f5f60808587031215611336575f5ffd5b61133f85611103565b935061134d60208601611103565b92506040850135915060608501356001600160401b0381111561136e575f5ffd5b61137a878288016112b8565b91505092959194509250565b5f5f60408385031215611397575f5ffd5b823591506113a760208401611103565b90509250929050565b634e487b7160e01b5f52602160045260245ffd5b60208101600483106113e457634e487b7160e01b5f52602160045260245ffd5b91905290565b5f5f83601f8401126113fa575f5ffd5b5081356001600160401b03811115611410575f5ffd5b6020830191508360208260051b850101111561115b575f5ffd5b5f5f5f5f5f5f5f5f5f60c08a8c031215611442575f5ffd5b89356001600160401b03811115611457575f5ffd5b6114638c828d016113ea565b909a5098505060208a01356001600160401b03811115611481575f5ffd5b61148d8c828d016113ea565b90985096505060408a01356001600160401b038111156114ab575f5ffd5b6114b78c828d016113ea565b9a9d999c50979a969997986060880135976080810135975060a0013595509350505050565b5f5f5f5f5f5f5f5f60a0898b0312156114f3575f5ffd5b88356001600160401b03811115611508575f5ffd5b6115148b828c016113ea565b90995097505060208901356001600160401b03811115611532575f5ffd5b61153e8b828c016113ea565b90975095505060408901356001600160401b0381111561155c575f5ffd5b6115688b828c016113ea565b999c989b509699959896976060870135966080013595509350505050565b5f82601f830112611595575f5ffd5b81356001600160401b038111156115ae576115ae611274565b8060051b6115be60208201611288565b918252602081850181019290810190868411156115d9575f5ffd5b6020860192505b838310156115fb5782358252602092830192909101906115e0565b9695505050505050565b5f5f5f5f5f60a08688031215611619575f5ffd5b61162286611103565b945061163060208701611103565b935060408601356001600160401b0381111561164a575f5ffd5b61165688828901611586565b93505060608601356001600160401b03811115611671575f5ffd5b61167d88828901611586565b92505060808601356001600160401b03811115611698575f5ffd5b6116a4888289016112b8565b9150509295509295909350565b5f5f5f5f5f60a086880312156116c5575f5ffd5b6116ce86611103565b94506116dc60208701611103565b9350604086013592506060860135915060808601356001600160401b03811115611698575f5ffd5b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b60018060a01b038716815285602082015260a060408201525f61175360a083018688611704565b60608301949094525060800152949350505050565b60018060a01b0385168152836020820152606060408201525f6115fb606083018486611704565b634e487b7160e01b5f52603260045260245ffd5b5f602082840312156117b3575f5ffd5b61083e82611103565b5f5f8335601e198436030181126117d1575f5ffd5b8301803591506001600160401b038211156117ea575f5ffd5b60200191503681900382131561115b575f5ffd5b5f8383855260208501945060208460051b820101835f5b8681101561188657838303601f19018852813536879003601e1901811261183a575f5ffd5b86016020810190356001600160401b03811115611855575f5ffd5b803603821315611863575f5ffd5b61186e858284611704565b60209a8b019a90955093909301925050600101611815565b50909695505050505050565b60a080825281018890525f8960c08301825b8b8110156118d2576001600160a01b036118bd84611103565b168252602092830192909101906001016118a4565b5083810360208501528881526001600160fb1b038911156118f1575f5ffd5b8860051b9150818a6020830137018281036020908101604085015261191990820187896117fe565b60608401959095525050608001529695505050505050565b8082018082111561069557634e487b7160e01b5f52601160045260245ffd5b818382375f910190815291905056fea2646970667358221220e6173ba0cadc9786932aa5be7c9644d0283de2cf799db818e672801f0259da7264736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/TransientSlot.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/TransientSlot.json new file mode 100644 index 00000000..b8e87586 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/TransientSlot.json @@ -0,0 +1,10 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "TransientSlot", + "sourceName": "contracts/utils/TransientSlot.sol", + "abi": [], + "bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122056e7566396f44ea053921930c5ee6ce15e653afb493fe8b609093d19f270272264736f6c634300081b0033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122056e7566396f44ea053921930c5ee6ce15e653afb493fe8b609093d19f270272264736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/TransparentUpgradeableProxy.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/TransparentUpgradeableProxy.json new file mode 100644 index 00000000..6f5bbcf8 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/TransparentUpgradeableProxy.json @@ -0,0 +1,116 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "TransparentUpgradeableProxy", + "sourceName": "contracts/proxy/transparent/TransparentUpgradeableProxy.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_logic", + "type": "address" + }, + { + "internalType": "address", + "name": "initialOwner", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "AddressEmptyCode", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "ERC1967InvalidAdmin", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "ERC1967InvalidImplementation", + "type": "error" + }, + { + "inputs": [], + "name": "ERC1967NonPayable", + "type": "error" + }, + { + "inputs": [], + "name": "FailedCall", + "type": "error" + }, + { + "inputs": [], + "name": "ProxyDeniedAdminAccess", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + } + ], + "bytecode": "0x60a0604052604051610dc7380380610dc783398101604081905261002291610369565b828161002e828261008c565b50508160405161003d9061032d565b6001600160a01b039091168152602001604051809103905ff080158015610066573d5f5f3e3d5ffd5b506001600160a01b031660805261008461007f60805190565b6100ea565b505050610450565b61009582610157565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a28051156100de576100d982826101d5565b505050565b6100e6610248565b5050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6101295f516020610da75f395f51905f52546001600160a01b031690565b604080516001600160a01b03928316815291841660208301520160405180910390a161015481610269565b50565b806001600160a01b03163b5f0361019157604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5b80546001600160a01b0319166001600160a01b039290921691909117905550565b60605f5f846001600160a01b0316846040516101f1919061043a565b5f60405180830381855af49150503d805f8114610229576040519150601f19603f3d011682016040523d82523d5f602084013e61022e565b606091505b50909250905061023f8583836102a6565b95945050505050565b34156102675760405163b398979f60e01b815260040160405180910390fd5b565b6001600160a01b03811661029257604051633173bdd160e11b81525f6004820152602401610188565b805f516020610da75f395f51905f526101b4565b6060826102bb576102b682610305565b6102fe565b81511580156102d257506001600160a01b0384163b155b156102fb57604051639996b31560e01b81526001600160a01b0385166004820152602401610188565b50805b9392505050565b80511561031457805160208201fd5b60405163d6bda27560e01b815260040160405180910390fd5b6104e6806108c183390190565b80516001600160a01b0381168114610350575f5ffd5b919050565b634e487b7160e01b5f52604160045260245ffd5b5f5f5f6060848603121561037b575f5ffd5b6103848461033a565b92506103926020850161033a565b60408501519092506001600160401b038111156103ad575f5ffd5b8401601f810186136103bd575f5ffd5b80516001600160401b038111156103d6576103d6610355565b604051601f8201601f19908116603f011681016001600160401b038111828210171561040457610404610355565b60405281815282820160200188101561041b575f5ffd5b8160208401602083015e5f602083830101528093505050509250925092565b5f82518060208501845e5f920191825250919050565b60805161045a6104675f395f6010015261045a5ff3fe608060405261000c61000e565b005b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316330361007a575f356001600160e01b03191663278f794360e11b14610070576040516334ad5dbb60e21b815260040160405180910390fd5b610078610082565b565b6100786100b0565b5f806100913660048184610302565b81019061009e919061033d565b915091506100ac82826100c0565b5050565b6100786100bb61011a565b610151565b6100c98261016f565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a28051156101125761010d82826101ea565b505050565b6100ac61025c565b5f61014c7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b905090565b365f5f375f5f365f845af43d5f5f3e80801561016b573d5ff35b3d5ffd5b806001600160a01b03163b5f036101a957604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0392909216919091179055565b60605f5f846001600160a01b031684604051610206919061040e565b5f60405180830381855af49150503d805f811461023e576040519150601f19603f3d011682016040523d82523d5f602084013e610243565b606091505b509150915061025385838361027b565b95945050505050565b34156100785760405163b398979f60e01b815260040160405180910390fd5b6060826102905761028b826102da565b6102d3565b81511580156102a757506001600160a01b0384163b155b156102d057604051639996b31560e01b81526001600160a01b03851660048201526024016101a0565b50805b9392505050565b8051156102e957805160208201fd5b60405163d6bda27560e01b815260040160405180910390fd5b5f5f85851115610310575f5ffd5b8386111561031c575f5ffd5b5050820193919092039150565b634e487b7160e01b5f52604160045260245ffd5b5f5f6040838503121561034e575f5ffd5b82356001600160a01b0381168114610364575f5ffd5b9150602083013567ffffffffffffffff81111561037f575f5ffd5b8301601f8101851361038f575f5ffd5b803567ffffffffffffffff8111156103a9576103a9610329565b604051601f8201601f19908116603f0116810167ffffffffffffffff811182821017156103d8576103d8610329565b6040528181528282016020018710156103ef575f5ffd5b816020840160208301375f602083830101528093505050509250929050565b5f82518060208501845e5f92019182525091905056fea26469706673582212208d27eb51f8e605a32f0ab717fdd826f5b6015244a3028e59d90e2ecb85f605b164736f6c634300081b00336080604052348015600e575f5ffd5b506040516104e63803806104e6833981016040819052602b9160b4565b806001600160a01b038116605857604051631e4fbdf760e01b81525f600482015260240160405180910390fd5b605f816065565b505060df565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b5f6020828403121560c3575f5ffd5b81516001600160a01b038116811460d8575f5ffd5b9392505050565b6103fa806100ec5f395ff3fe608060405260043610610049575f3560e01c8063715018a61461004d5780638da5cb5b146100635780639623609d1461008e578063ad3cb1cc146100a1578063f2fde38b146100de575b5f5ffd5b348015610058575f5ffd5b506100616100fd565b005b34801561006e575f5ffd5b505f546040516001600160a01b0390911681526020015b60405180910390f35b61006161009c366004610260565b610110565b3480156100ac575f5ffd5b506100d1604051806040016040528060058152602001640352e302e360dc1b81525081565b6040516100859190610365565b3480156100e9575f5ffd5b506100616100f836600461037e565b61017b565b6101056101bd565b61010e5f6101e9565b565b6101186101bd565b60405163278f794360e11b81526001600160a01b03841690634f1ef2869034906101489086908690600401610399565b5f604051808303818588803b15801561015f575f5ffd5b505af1158015610171573d5f5f3e3d5ffd5b5050505050505050565b6101836101bd565b6001600160a01b0381166101b157604051631e4fbdf760e01b81525f60048201526024015b60405180910390fd5b6101ba816101e9565b50565b5f546001600160a01b0316331461010e5760405163118cdaa760e01b81523360048201526024016101a8565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811681146101ba575f5ffd5b634e487b7160e01b5f52604160045260245ffd5b5f5f5f60608486031215610272575f5ffd5b833561027d81610238565b9250602084013561028d81610238565b9150604084013567ffffffffffffffff8111156102a8575f5ffd5b8401601f810186136102b8575f5ffd5b803567ffffffffffffffff8111156102d2576102d261024c565b604051601f8201601f19908116603f0116810167ffffffffffffffff811182821017156103015761030161024c565b604052818152828201602001881015610318575f5ffd5b816020840160208301375f602083830101528093505050509250925092565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f6103776020830184610337565b9392505050565b5f6020828403121561038e575f5ffd5b813561037781610238565b6001600160a01b03831681526040602082018190525f906103bc90830184610337565b94935050505056fea2646970667358221220787d2d426698dd68d81e8b7441ae3962906d711359b9b4f0d0836c9c0df5687564736f6c634300081b0033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103", + "deployedBytecode": "0x608060405261000c61000e565b005b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316330361007a575f356001600160e01b03191663278f794360e11b14610070576040516334ad5dbb60e21b815260040160405180910390fd5b610078610082565b565b6100786100b0565b5f806100913660048184610302565b81019061009e919061033d565b915091506100ac82826100c0565b5050565b6100786100bb61011a565b610151565b6100c98261016f565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a28051156101125761010d82826101ea565b505050565b6100ac61025c565b5f61014c7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b905090565b365f5f375f5f365f845af43d5f5f3e80801561016b573d5ff35b3d5ffd5b806001600160a01b03163b5f036101a957604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0392909216919091179055565b60605f5f846001600160a01b031684604051610206919061040e565b5f60405180830381855af49150503d805f811461023e576040519150601f19603f3d011682016040523d82523d5f602084013e610243565b606091505b509150915061025385838361027b565b95945050505050565b34156100785760405163b398979f60e01b815260040160405180910390fd5b6060826102905761028b826102da565b6102d3565b81511580156102a757506001600160a01b0384163b155b156102d057604051639996b31560e01b81526001600160a01b03851660048201526024016101a0565b50805b9392505050565b8051156102e957805160208201fd5b60405163d6bda27560e01b815260040160405180910390fd5b5f5f85851115610310575f5ffd5b8386111561031c575f5ffd5b5050820193919092039150565b634e487b7160e01b5f52604160045260245ffd5b5f5f6040838503121561034e575f5ffd5b82356001600160a01b0381168114610364575f5ffd5b9150602083013567ffffffffffffffff81111561037f575f5ffd5b8301601f8101851361038f575f5ffd5b803567ffffffffffffffff8111156103a9576103a9610329565b604051601f8201601f19908116603f0116810167ffffffffffffffff811182821017156103d8576103d8610329565b6040528181528282016020018710156103ef575f5ffd5b816020840160208301375f602083830101528093505050509250929050565b5f82518060208501845e5f92019182525091905056fea26469706673582212208d27eb51f8e605a32f0ab717fdd826f5b6015244a3028e59d90e2ecb85f605b164736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/UUPSUpgradeable.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/UUPSUpgradeable.json new file mode 100644 index 00000000..54382c74 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/UUPSUpgradeable.json @@ -0,0 +1,116 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "UUPSUpgradeable", + "sourceName": "contracts/proxy/utils/UUPSUpgradeable.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "AddressEmptyCode", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "ERC1967InvalidImplementation", + "type": "error" + }, + { + "inputs": [], + "name": "ERC1967NonPayable", + "type": "error" + }, + { + "inputs": [], + "name": "FailedCall", + "type": "error" + }, + { + "inputs": [], + "name": "UUPSUnauthorizedCallContext", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "slot", + "type": "bytes32" + } + ], + "name": "UUPSUnsupportedProxiableUUID", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "inputs": [], + "name": "UPGRADE_INTERFACE_VERSION", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/UpgradeableBeacon.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/UpgradeableBeacon.json new file mode 100644 index 00000000..6353559c --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/UpgradeableBeacon.json @@ -0,0 +1,151 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "UpgradeableBeacon", + "sourceName": "contracts/proxy/beacon/UpgradeableBeacon.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + }, + { + "internalType": "address", + "name": "initialOwner", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "BeaconInvalidImplementation", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnableInvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "OwnableUnauthorizedAccount", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x608060405234801561000f575f5ffd5b5060405161042138038061042183398101604081905261002e9161015f565b806001600160a01b03811661005d57604051631e4fbdf760e01b81525f60048201526024015b60405180910390fd5b61006681610077565b50610070826100c6565b5050610190565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b806001600160a01b03163b5f036100fb5760405163211eb15960e21b81526001600160a01b0382166004820152602401610054565b600180546001600160a01b0319166001600160a01b0383169081179091556040517fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b80516001600160a01b038116811461015a575f5ffd5b919050565b5f5f60408385031215610170575f5ffd5b61017983610144565b915061018760208401610144565b90509250929050565b6102848061019d5f395ff3fe608060405234801561000f575f5ffd5b5060043610610055575f3560e01c80633659cfe6146100595780635c60da1b1461006e578063715018a6146100975780638da5cb5b1461009f578063f2fde38b146100af575b5f5ffd5b61006c610067366004610221565b6100c2565b005b6001546001600160a01b03165b6040516001600160a01b03909116815260200160405180910390f35b61006c6100d6565b5f546001600160a01b031661007b565b61006c6100bd366004610221565b6100e9565b6100ca610128565b6100d381610154565b50565b6100de610128565b6100e75f6101d2565b565b6100f1610128565b6001600160a01b03811661011f57604051631e4fbdf760e01b81525f60048201526024015b60405180910390fd5b6100d3816101d2565b5f546001600160a01b031633146100e75760405163118cdaa760e01b8152336004820152602401610116565b806001600160a01b03163b5f036101895760405163211eb15960e21b81526001600160a01b0382166004820152602401610116565b600180546001600160a01b0319166001600160a01b0383169081179091556040517fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b5f60208284031215610231575f5ffd5b81356001600160a01b0381168114610247575f5ffd5b939250505056fea264697066735822122085d01e60d91b3008d8108f0464ce5af78ace614cd48711dfeeaa2f8206dddf7164736f6c634300081b0033", + "deployedBytecode": "0x608060405234801561000f575f5ffd5b5060043610610055575f3560e01c80633659cfe6146100595780635c60da1b1461006e578063715018a6146100975780638da5cb5b1461009f578063f2fde38b146100af575b5f5ffd5b61006c610067366004610221565b6100c2565b005b6001546001600160a01b03165b6040516001600160a01b03909116815260200160405180910390f35b61006c6100d6565b5f546001600160a01b031661007b565b61006c6100bd366004610221565b6100e9565b6100ca610128565b6100d381610154565b50565b6100de610128565b6100e75f6101d2565b565b6100f1610128565b6001600160a01b03811661011f57604051631e4fbdf760e01b81525f60048201526024015b60405180910390fd5b6100d3816101d2565b5f546001600160a01b031633146100e75760405163118cdaa760e01b8152336004820152602401610116565b806001600160a01b03163b5f036101895760405163211eb15960e21b81526001600160a01b0382166004820152602401610116565b600180546001600160a01b0319166001600160a01b0383169081179091556040517fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b5f60208284031215610231575f5ffd5b81356001600160a01b0381168114610247575f5ffd5b939250505056fea264697066735822122085d01e60d91b3008d8108f0464ce5af78ace614cd48711dfeeaa2f8206dddf7164736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/VestingWallet.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/VestingWallet.json new file mode 100644 index 00000000..0e7efdb9 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/VestingWallet.json @@ -0,0 +1,340 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "VestingWallet", + "sourceName": "contracts/finance/VestingWallet.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "internalType": "uint64", + "name": "startTimestamp", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "durationSeconds", + "type": "uint64" + } + ], + "stateMutability": "payable", + "type": "constructor" + }, + { + "inputs": [], + "name": "FailedCall", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + } + ], + "name": "InsufficientBalance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnableInvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "OwnableUnauthorizedAccount", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "SafeERC20FailedOperation", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "ERC20Released", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "EtherReleased", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "duration", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "end", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "releasable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "releasable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "release", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "release", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "released", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "released", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "start", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "timestamp", + "type": "uint64" + } + ], + "name": "vestedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint64", + "name": "timestamp", + "type": "uint64" + } + ], + "name": "vestedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "bytecode": "0x60c0604052604051610ab4380380610ab4833981016040819052610022916100dc565b826001600160a01b03811661005057604051631e4fbdf760e01b81525f600482015260240160405180910390fd5b61005981610072565b506001600160401b039182166080521660a05250610129565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160401b03811681146100d7575f5ffd5b919050565b5f5f5f606084860312156100ee575f5ffd5b83516001600160a01b0381168114610104575f5ffd5b9250610112602085016100c1565b9150610120604085016100c1565b90509250925092565b60805160a05161095c6101585f395f8181610127015281816104d401526105b201525f6104ae015261095c5ff3fe6080604052600436106100dc575f3560e01c8063961325211161007c578063be9a655511610057578063be9a65551461024a578063efbe1c1c1461025e578063f2fde38b14610272578063fbccedae14610291575f5ffd5b806396132521146101e35780639852595c146101f7578063a3f8eace1461022b575f5ffd5b8063715018a6116100b7578063715018a614610176578063810ec23b1461018a57806386d1a69f146101a95780638da5cb5b146101bd575f5ffd5b80630a17b06b146100e75780630fb5a6b4146101195780631916558714610155575f5ffd5b366100e357005b5f5ffd5b3480156100f2575f5ffd5b50610106610101366004610826565b6102a5565b6040519081526020015b60405180910390f35b348015610124575f5ffd5b507f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff16610106565b348015610160575f5ffd5b5061017461016f366004610855565b6102c8565b005b348015610181575f5ffd5b50610174610360565b348015610195575f5ffd5b506101066101a436600461086e565b610373565b3480156101b4575f5ffd5b50610174610406565b3480156101c8575f5ffd5b505f546040516001600160a01b039091168152602001610110565b3480156101ee575f5ffd5b50600154610106565b348015610202575f5ffd5b50610106610211366004610855565b6001600160a01b03165f9081526002602052604090205490565b348015610236575f5ffd5b50610106610245366004610855565b610477565b348015610255575f5ffd5b506101066104a3565b348015610269575f5ffd5b506101066104d1565b34801561027d575f5ffd5b5061017461028c366004610855565b610514565b34801561029c575f5ffd5b50610106610553565b5f6102c26102b260015490565b6102bc90476108b3565b83610570565b92915050565b5f6102d282610477565b6001600160a01b0383165f908152600260205260408120805492935083929091906102fe9084906108b3565b90915550506040518181526001600160a01b038316907fc0e523490dd523c33b1878c9eb14ff46991e3f5b2cd33710918618f2a39cba1b9060200160405180910390a261035c826103565f546001600160a01b031690565b83610612565b5050565b610368610669565b6103715f610695565b565b6001600160a01b0382165f908152600260205260408120546103ff906040516370a0823160e01b81523060048201526001600160a01b038616906370a0823190602401602060405180830381865afa1580156103d1573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103f591906108c6565b6102bc91906108b3565b9392505050565b5f61040f610553565b90508060015f82825461042291906108b3565b90915550506040518181527fda9d4e5f101b8b9b1c5b76d0c5a9f7923571acfc02376aa076b75a8c080c956b9060200160405180910390a161047461046e5f546001600160a01b031690565b826106e4565b50565b6001600160a01b0381165f908152600260205260408120546104998342610373565b6102c291906108dd565b67ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690565b5f7f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff166105056104a3565b61050f91906108b3565b905090565b61051c610669565b6001600160a01b03811661054a57604051631e4fbdf760e01b81525f60048201526024015b60405180910390fd5b61047481610695565b5f61055d60015490565b610566426102a5565b61050f91906108dd565b5f6105796104a3565b8267ffffffffffffffff16101561059157505f6102c2565b6105996104d1565b8267ffffffffffffffff16106105b05750816102c2565b7f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff166105e36104a3565b6105f79067ffffffffffffffff85166108dd565b61060190856108f0565b61060b9190610907565b90506102c2565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052610664908490610776565b505050565b5f546001600160a01b031633146103715760405163118cdaa760e01b8152336004820152602401610541565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b8047101561070e5760405163cf47918160e01b815247600482015260248101829052604401610541565b5f5f836001600160a01b0316836040515f6040518083038185875af1925050503d805f8114610758576040519150601f19603f3d011682016040523d82523d5f602084013e61075d565b606091505b50915091508161077057610770816107e2565b50505050565b5f5f60205f8451602086015f885af180610795576040513d5f823e3d81fd5b50505f513d915081156107ac5780600114156107b9565b6001600160a01b0384163b155b1561077057604051635274afe760e01b81526001600160a01b0385166004820152602401610541565b8051156107f157805160208201fd5b60405163d6bda27560e01b815260040160405180910390fd5b803567ffffffffffffffff81168114610821575f5ffd5b919050565b5f60208284031215610836575f5ffd5b6103ff8261080a565b80356001600160a01b0381168114610821575f5ffd5b5f60208284031215610865575f5ffd5b6103ff8261083f565b5f5f6040838503121561087f575f5ffd5b6108888361083f565b91506108966020840161080a565b90509250929050565b634e487b7160e01b5f52601160045260245ffd5b808201808211156102c2576102c261089f565b5f602082840312156108d6575f5ffd5b5051919050565b818103818111156102c2576102c261089f565b80820281158282048414176102c2576102c261089f565b5f8261092157634e487b7160e01b5f52601260045260245ffd5b50049056fea2646970667358221220fa78cb5f83707ccaacb0a1f0b8074c2d520d9f268f0815a78a88b13e3937431b64736f6c634300081b0033", + "deployedBytecode": "0x6080604052600436106100dc575f3560e01c8063961325211161007c578063be9a655511610057578063be9a65551461024a578063efbe1c1c1461025e578063f2fde38b14610272578063fbccedae14610291575f5ffd5b806396132521146101e35780639852595c146101f7578063a3f8eace1461022b575f5ffd5b8063715018a6116100b7578063715018a614610176578063810ec23b1461018a57806386d1a69f146101a95780638da5cb5b146101bd575f5ffd5b80630a17b06b146100e75780630fb5a6b4146101195780631916558714610155575f5ffd5b366100e357005b5f5ffd5b3480156100f2575f5ffd5b50610106610101366004610826565b6102a5565b6040519081526020015b60405180910390f35b348015610124575f5ffd5b507f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff16610106565b348015610160575f5ffd5b5061017461016f366004610855565b6102c8565b005b348015610181575f5ffd5b50610174610360565b348015610195575f5ffd5b506101066101a436600461086e565b610373565b3480156101b4575f5ffd5b50610174610406565b3480156101c8575f5ffd5b505f546040516001600160a01b039091168152602001610110565b3480156101ee575f5ffd5b50600154610106565b348015610202575f5ffd5b50610106610211366004610855565b6001600160a01b03165f9081526002602052604090205490565b348015610236575f5ffd5b50610106610245366004610855565b610477565b348015610255575f5ffd5b506101066104a3565b348015610269575f5ffd5b506101066104d1565b34801561027d575f5ffd5b5061017461028c366004610855565b610514565b34801561029c575f5ffd5b50610106610553565b5f6102c26102b260015490565b6102bc90476108b3565b83610570565b92915050565b5f6102d282610477565b6001600160a01b0383165f908152600260205260408120805492935083929091906102fe9084906108b3565b90915550506040518181526001600160a01b038316907fc0e523490dd523c33b1878c9eb14ff46991e3f5b2cd33710918618f2a39cba1b9060200160405180910390a261035c826103565f546001600160a01b031690565b83610612565b5050565b610368610669565b6103715f610695565b565b6001600160a01b0382165f908152600260205260408120546103ff906040516370a0823160e01b81523060048201526001600160a01b038616906370a0823190602401602060405180830381865afa1580156103d1573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103f591906108c6565b6102bc91906108b3565b9392505050565b5f61040f610553565b90508060015f82825461042291906108b3565b90915550506040518181527fda9d4e5f101b8b9b1c5b76d0c5a9f7923571acfc02376aa076b75a8c080c956b9060200160405180910390a161047461046e5f546001600160a01b031690565b826106e4565b50565b6001600160a01b0381165f908152600260205260408120546104998342610373565b6102c291906108dd565b67ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690565b5f7f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff166105056104a3565b61050f91906108b3565b905090565b61051c610669565b6001600160a01b03811661054a57604051631e4fbdf760e01b81525f60048201526024015b60405180910390fd5b61047481610695565b5f61055d60015490565b610566426102a5565b61050f91906108dd565b5f6105796104a3565b8267ffffffffffffffff16101561059157505f6102c2565b6105996104d1565b8267ffffffffffffffff16106105b05750816102c2565b7f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff166105e36104a3565b6105f79067ffffffffffffffff85166108dd565b61060190856108f0565b61060b9190610907565b90506102c2565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052610664908490610776565b505050565b5f546001600160a01b031633146103715760405163118cdaa760e01b8152336004820152602401610541565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b8047101561070e5760405163cf47918160e01b815247600482015260248101829052604401610541565b5f5f836001600160a01b0316836040515f6040518083038185875af1925050503d805f8114610758576040519150601f19603f3d011682016040523d82523d5f602084013e61075d565b606091505b50915091508161077057610770816107e2565b50505050565b5f5f60205f8451602086015f885af180610795576040513d5f823e3d81fd5b50505f513d915081156107ac5780600114156107b9565b6001600160a01b0384163b155b1561077057604051635274afe760e01b81526001600160a01b0385166004820152602401610541565b8051156107f157805160208201fd5b60405163d6bda27560e01b815260040160405180910390fd5b803567ffffffffffffffff81168114610821575f5ffd5b919050565b5f60208284031215610836575f5ffd5b6103ff8261080a565b80356001600160a01b0381168114610821575f5ffd5b5f60208284031215610865575f5ffd5b6103ff8261083f565b5f5f6040838503121561087f575f5ffd5b6108888361083f565b91506108966020840161080a565b90509250929050565b634e487b7160e01b5f52601160045260245ffd5b808201808211156102c2576102c261089f565b5f602082840312156108d6575f5ffd5b5051919050565b818103818111156102c2576102c261089f565b80820281158282048414176102c2576102c261089f565b5f8261092157634e487b7160e01b5f52601260045260245ffd5b50049056fea2646970667358221220fa78cb5f83707ccaacb0a1f0b8074c2d520d9f268f0815a78a88b13e3937431b64736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/VestingWalletCliff.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/VestingWalletCliff.json new file mode 100644 index 00000000..adda7b3e --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/VestingWalletCliff.json @@ -0,0 +1,364 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "VestingWalletCliff", + "sourceName": "contracts/finance/VestingWalletCliff.sol", + "abi": [ + { + "inputs": [], + "name": "FailedCall", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + } + ], + "name": "InsufficientBalance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "cliffSeconds", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "durationSeconds", + "type": "uint64" + } + ], + "name": "InvalidCliffDuration", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnableInvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "OwnableUnauthorizedAccount", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "bits", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "SafeCastOverflowedUintDowncast", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "SafeERC20FailedOperation", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "ERC20Released", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "EtherReleased", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "cliff", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "duration", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "end", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "releasable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "releasable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "release", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "release", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "released", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "released", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "start", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "timestamp", + "type": "uint64" + } + ], + "name": "vestedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint64", + "name": "timestamp", + "type": "uint64" + } + ], + "name": "vestedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Votes.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Votes.json new file mode 100644 index 00000000..1950028f --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/Votes.json @@ -0,0 +1,399 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "Votes", + "sourceName": "contracts/governance/utils/Votes.sol", + "abi": [ + { + "inputs": [], + "name": "CheckpointUnorderedInsertion", + "type": "error" + }, + { + "inputs": [], + "name": "ECDSAInvalidSignature", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "length", + "type": "uint256" + } + ], + "name": "ECDSAInvalidSignatureLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "ECDSAInvalidSignatureS", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + }, + { + "internalType": "uint48", + "name": "clock", + "type": "uint48" + } + ], + "name": "ERC5805FutureLookup", + "type": "error" + }, + { + "inputs": [], + "name": "ERC6372InconsistentClock", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "currentNonce", + "type": "uint256" + } + ], + "name": "InvalidAccountNonce", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidShortString", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "bits", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "SafeCastOverflowedUintDowncast", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "str", + "type": "string" + } + ], + "name": "StringTooLong", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "expiry", + "type": "uint256" + } + ], + "name": "VotesExpiredSignature", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "delegator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "fromDelegate", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "toDelegate", + "type": "address" + } + ], + "name": "DelegateChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "delegate", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "previousVotes", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newVotes", + "type": "uint256" + } + ], + "name": "DelegateVotesChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "EIP712DomainChanged", + "type": "event" + }, + { + "inputs": [], + "name": "CLOCK_MODE", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "clock", + "outputs": [ + { + "internalType": "uint48", + "name": "", + "type": "uint48" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "delegatee", + "type": "address" + } + ], + "name": "delegate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "delegatee", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "expiry", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "delegateBySig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "delegates", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "eip712Domain", + "outputs": [ + { + "internalType": "bytes1", + "name": "fields", + "type": "bytes1" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "version", + "type": "string" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "verifyingContract", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + }, + { + "internalType": "uint256[]", + "name": "extensions", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + } + ], + "name": "getPastTotalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + } + ], + "name": "getPastVotes", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getVotes", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/VotesExtended.json b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/VotesExtended.json new file mode 100644 index 00000000..7ae99517 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/build/contracts/VotesExtended.json @@ -0,0 +1,447 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "VotesExtended", + "sourceName": "contracts/governance/utils/VotesExtended.sol", + "abi": [ + { + "inputs": [], + "name": "CheckpointUnorderedInsertion", + "type": "error" + }, + { + "inputs": [], + "name": "ECDSAInvalidSignature", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "length", + "type": "uint256" + } + ], + "name": "ECDSAInvalidSignatureLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "ECDSAInvalidSignatureS", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + }, + { + "internalType": "uint48", + "name": "clock", + "type": "uint48" + } + ], + "name": "ERC5805FutureLookup", + "type": "error" + }, + { + "inputs": [], + "name": "ERC6372InconsistentClock", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "currentNonce", + "type": "uint256" + } + ], + "name": "InvalidAccountNonce", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidShortString", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "bits", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "SafeCastOverflowedUintDowncast", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "str", + "type": "string" + } + ], + "name": "StringTooLong", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "expiry", + "type": "uint256" + } + ], + "name": "VotesExpiredSignature", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "delegator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "fromDelegate", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "toDelegate", + "type": "address" + } + ], + "name": "DelegateChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "delegate", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "previousVotes", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newVotes", + "type": "uint256" + } + ], + "name": "DelegateVotesChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "EIP712DomainChanged", + "type": "event" + }, + { + "inputs": [], + "name": "CLOCK_MODE", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "clock", + "outputs": [ + { + "internalType": "uint48", + "name": "", + "type": "uint48" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "delegatee", + "type": "address" + } + ], + "name": "delegate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "delegatee", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "expiry", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "delegateBySig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "delegates", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "eip712Domain", + "outputs": [ + { + "internalType": "bytes1", + "name": "fields", + "type": "bytes1" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "version", + "type": "string" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "verifyingContract", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + }, + { + "internalType": "uint256[]", + "name": "extensions", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + } + ], + "name": "getPastBalanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + } + ], + "name": "getPastDelegate", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + } + ], + "name": "getPastTotalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "timepoint", + "type": "uint256" + } + ], + "name": "getPastVotes", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getVotes", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/finance/VestingWallet.sol b/dependencies/@openzeppelin-contracts-5.4.0/finance/VestingWallet.sol new file mode 100644 index 00000000..03024fae --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/finance/VestingWallet.sol @@ -0,0 +1,159 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.3.0) (finance/VestingWallet.sol) +pragma solidity ^0.8.20; + +import {IERC20} from "../token/ERC20/IERC20.sol"; +import {SafeERC20} from "../token/ERC20/utils/SafeERC20.sol"; +import {Address} from "../utils/Address.sol"; +import {Context} from "../utils/Context.sol"; +import {Ownable} from "../access/Ownable.sol"; + +/** + * @dev A vesting wallet is an ownable contract that can receive native currency and ERC-20 tokens, and release these + * assets to the wallet owner, also referred to as "beneficiary", according to a vesting schedule. + * + * Any assets transferred to this contract will follow the vesting schedule as if they were locked from the beginning. + * Consequently, if the vesting has already started, any amount of tokens sent to this contract will (at least partly) + * be immediately releasable. + * + * By setting the duration to 0, one can configure this contract to behave like an asset timelock that holds tokens for + * a beneficiary until a specified time. + * + * NOTE: Since the wallet is {Ownable}, and ownership can be transferred, it is possible to sell unvested tokens. + * Preventing this in a smart contract is difficult, considering that: 1) a beneficiary address could be a + * counterfactually deployed contract, 2) there is likely to be a migration path for EOAs to become contracts in the + * near future. + * + * NOTE: When using this contract with any token whose balance is adjusted automatically (i.e. a rebase token), make + * sure to account the supply/balance adjustment in the vesting schedule to ensure the vested amount is as intended. + * + * NOTE: Chains with support for native ERC20s may allow the vesting wallet to withdraw the underlying asset as both an + * ERC20 and as native currency. For example, if chain C supports token A and the wallet gets deposited 100 A, then + * at 50% of the vesting period, the beneficiary can withdraw 50 A as ERC20 and 25 A as native currency (totaling 75 A). + * Consider disabling one of the withdrawal methods. + */ +contract VestingWallet is Context, Ownable { + event EtherReleased(uint256 amount); + event ERC20Released(address indexed token, uint256 amount); + + uint256 private _released; + mapping(address token => uint256) private _erc20Released; + uint64 private immutable _start; + uint64 private immutable _duration; + + /** + * @dev Sets the beneficiary (owner), the start timestamp and the vesting duration (in seconds) of the vesting + * wallet. + */ + constructor(address beneficiary, uint64 startTimestamp, uint64 durationSeconds) payable Ownable(beneficiary) { + _start = startTimestamp; + _duration = durationSeconds; + } + + /** + * @dev The contract should be able to receive Eth. + */ + receive() external payable virtual {} + + /** + * @dev Getter for the start timestamp. + */ + function start() public view virtual returns (uint256) { + return _start; + } + + /** + * @dev Getter for the vesting duration. + */ + function duration() public view virtual returns (uint256) { + return _duration; + } + + /** + * @dev Getter for the end timestamp. + */ + function end() public view virtual returns (uint256) { + return start() + duration(); + } + + /** + * @dev Amount of eth already released + */ + function released() public view virtual returns (uint256) { + return _released; + } + + /** + * @dev Amount of token already released + */ + function released(address token) public view virtual returns (uint256) { + return _erc20Released[token]; + } + + /** + * @dev Getter for the amount of releasable eth. + */ + function releasable() public view virtual returns (uint256) { + return vestedAmount(uint64(block.timestamp)) - released(); + } + + /** + * @dev Getter for the amount of releasable `token` tokens. `token` should be the address of an + * {IERC20} contract. + */ + function releasable(address token) public view virtual returns (uint256) { + return vestedAmount(token, uint64(block.timestamp)) - released(token); + } + + /** + * @dev Release the native token (ether) that have already vested. + * + * Emits a {EtherReleased} event. + */ + function release() public virtual { + uint256 amount = releasable(); + _released += amount; + emit EtherReleased(amount); + Address.sendValue(payable(owner()), amount); + } + + /** + * @dev Release the tokens that have already vested. + * + * Emits a {ERC20Released} event. + */ + function release(address token) public virtual { + uint256 amount = releasable(token); + _erc20Released[token] += amount; + emit ERC20Released(token, amount); + SafeERC20.safeTransfer(IERC20(token), owner(), amount); + } + + /** + * @dev Calculates the amount of ether that has already vested. Default implementation is a linear vesting curve. + */ + function vestedAmount(uint64 timestamp) public view virtual returns (uint256) { + return _vestingSchedule(address(this).balance + released(), timestamp); + } + + /** + * @dev Calculates the amount of tokens that has already vested. Default implementation is a linear vesting curve. + */ + function vestedAmount(address token, uint64 timestamp) public view virtual returns (uint256) { + return _vestingSchedule(IERC20(token).balanceOf(address(this)) + released(token), timestamp); + } + + /** + * @dev Virtual implementation of the vesting formula. This returns the amount vested, as a function of time, for + * an asset given its total historical allocation. + */ + function _vestingSchedule(uint256 totalAllocation, uint64 timestamp) internal view virtual returns (uint256) { + if (timestamp < start()) { + return 0; + } else if (timestamp >= end()) { + return totalAllocation; + } else { + return (totalAllocation * (timestamp - start())) / duration(); + } + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/finance/VestingWalletCliff.sol b/dependencies/@openzeppelin-contracts-5.4.0/finance/VestingWalletCliff.sol new file mode 100644 index 00000000..dd1da658 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/finance/VestingWalletCliff.sol @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.1.0) (finance/VestingWalletCliff.sol) + +pragma solidity ^0.8.20; + +import {SafeCast} from "../utils/math/SafeCast.sol"; +import {VestingWallet} from "./VestingWallet.sol"; + +/** + * @dev Extension of {VestingWallet} that adds a cliff to the vesting schedule. + * + * _Available since v5.1._ + */ +abstract contract VestingWalletCliff is VestingWallet { + using SafeCast for *; + + uint64 private immutable _cliff; + + /// @dev The specified cliff duration is larger than the vesting duration. + error InvalidCliffDuration(uint64 cliffSeconds, uint64 durationSeconds); + + /** + * @dev Set the duration of the cliff, in seconds. The cliff starts vesting schedule (see {VestingWallet}'s + * constructor) and ends `cliffSeconds` later. + */ + constructor(uint64 cliffSeconds) { + if (cliffSeconds > duration()) { + revert InvalidCliffDuration(cliffSeconds, duration().toUint64()); + } + _cliff = start().toUint64() + cliffSeconds; + } + + /** + * @dev Getter for the cliff timestamp. + */ + function cliff() public view virtual returns (uint256) { + return _cliff; + } + + /** + * @dev Virtual implementation of the vesting formula. This returns the amount vested, as a function of time, for + * an asset given its total historical allocation. Returns 0 if the {cliff} timestamp is not met. + * + * IMPORTANT: The cliff not only makes the schedule return 0, but it also ignores every possible side + * effect from calling the inherited implementation (i.e. `super._vestingSchedule`). Carefully consider + * this caveat if the overridden implementation of this function has any (e.g. writing to memory or reverting). + */ + function _vestingSchedule( + uint256 totalAllocation, + uint64 timestamp + ) internal view virtual override returns (uint256) { + return timestamp < cliff() ? 0 : super._vestingSchedule(totalAllocation, timestamp); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/governance/Governor.sol b/dependencies/@openzeppelin-contracts-5.4.0/governance/Governor.sol new file mode 100644 index 00000000..05564b83 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/governance/Governor.sol @@ -0,0 +1,818 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (governance/Governor.sol) + +pragma solidity ^0.8.24; + +import {IERC721Receiver} from "../token/ERC721/IERC721Receiver.sol"; +import {IERC1155Receiver} from "../token/ERC1155/IERC1155Receiver.sol"; +import {EIP712} from "../utils/cryptography/EIP712.sol"; +import {SignatureChecker} from "../utils/cryptography/SignatureChecker.sol"; +import {IERC165, ERC165} from "../utils/introspection/ERC165.sol"; +import {SafeCast} from "../utils/math/SafeCast.sol"; +import {DoubleEndedQueue} from "../utils/structs/DoubleEndedQueue.sol"; +import {Address} from "../utils/Address.sol"; +import {Context} from "../utils/Context.sol"; +import {Nonces} from "../utils/Nonces.sol"; +import {Strings} from "../utils/Strings.sol"; +import {IGovernor, IERC6372} from "./IGovernor.sol"; + +/** + * @dev Core of the governance system, designed to be extended through various modules. + * + * This contract is abstract and requires several functions to be implemented in various modules: + * + * - A counting module must implement {_quorumReached}, {_voteSucceeded} and {_countVote} + * - A voting module must implement {_getVotes} + * - Additionally, {votingPeriod}, {votingDelay}, and {quorum} must also be implemented + */ +abstract contract Governor is Context, ERC165, EIP712, Nonces, IGovernor, IERC721Receiver, IERC1155Receiver { + using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque; + + bytes32 public constant BALLOT_TYPEHASH = + keccak256("Ballot(uint256 proposalId,uint8 support,address voter,uint256 nonce)"); + bytes32 public constant EXTENDED_BALLOT_TYPEHASH = + keccak256( + "ExtendedBallot(uint256 proposalId,uint8 support,address voter,uint256 nonce,string reason,bytes params)" + ); + + struct ProposalCore { + address proposer; + uint48 voteStart; + uint32 voteDuration; + bool executed; + bool canceled; + uint48 etaSeconds; + } + + bytes32 private constant ALL_PROPOSAL_STATES_BITMAP = bytes32((2 ** (uint8(type(ProposalState).max) + 1)) - 1); + string private _name; + + mapping(uint256 proposalId => ProposalCore) private _proposals; + + // This queue keeps track of the governor operating on itself. Calls to functions protected by the {onlyGovernance} + // modifier needs to be whitelisted in this queue. Whitelisting is set in {execute}, consumed by the + // {onlyGovernance} modifier and eventually reset after {_executeOperations} completes. This ensures that the + // execution of {onlyGovernance} protected calls can only be achieved through successful proposals. + DoubleEndedQueue.Bytes32Deque private _governanceCall; + + /** + * @dev Restricts a function so it can only be executed through governance proposals. For example, governance + * parameter setters in {GovernorSettings} are protected using this modifier. + * + * The governance executing address may be different from the Governor's own address, for example it could be a + * timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these + * functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus, + * for example, additional timelock proposers are not able to change governance parameters without going through the + * governance protocol (since v4.6). + */ + modifier onlyGovernance() { + _checkGovernance(); + _; + } + + /** + * @dev Sets the value for {name} and {version} + */ + constructor(string memory name_) EIP712(name_, version()) { + _name = name_; + } + + /** + * @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract) + */ + receive() external payable virtual { + if (_executor() != address(this)) { + revert GovernorDisabledDeposit(); + } + } + + /// @inheritdoc IERC165 + function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) { + return + interfaceId == type(IGovernor).interfaceId || + interfaceId == type(IGovernor).interfaceId ^ IGovernor.getProposalId.selector || + interfaceId == type(IERC1155Receiver).interfaceId || + super.supportsInterface(interfaceId); + } + + /// @inheritdoc IGovernor + function name() public view virtual returns (string memory) { + return _name; + } + + /// @inheritdoc IGovernor + function version() public view virtual returns (string memory) { + return "1"; + } + + /** + * @dev See {IGovernor-hashProposal}. + * + * The proposal id is produced by hashing the ABI encoded `targets` array, the `values` array, the `calldatas` array + * and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id + * can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in + * advance, before the proposal is submitted. + * + * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the + * same proposal (with same operation and same description) will have the same id if submitted on multiple governors + * across multiple networks. This also means that in order to execute the same operation twice (on the same + * governor) the proposer will have to change the description in order to avoid proposal id conflicts. + */ + function hashProposal( + address[] memory targets, + uint256[] memory values, + bytes[] memory calldatas, + bytes32 descriptionHash + ) public pure virtual returns (uint256) { + return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash))); + } + + /// @inheritdoc IGovernor + function getProposalId( + address[] memory targets, + uint256[] memory values, + bytes[] memory calldatas, + bytes32 descriptionHash + ) public view virtual returns (uint256) { + return hashProposal(targets, values, calldatas, descriptionHash); + } + + /// @inheritdoc IGovernor + function state(uint256 proposalId) public view virtual returns (ProposalState) { + // We read the struct fields into the stack at once so Solidity emits a single SLOAD + ProposalCore storage proposal = _proposals[proposalId]; + bool proposalExecuted = proposal.executed; + bool proposalCanceled = proposal.canceled; + + if (proposalExecuted) { + return ProposalState.Executed; + } + + if (proposalCanceled) { + return ProposalState.Canceled; + } + + uint256 snapshot = proposalSnapshot(proposalId); + + if (snapshot == 0) { + revert GovernorNonexistentProposal(proposalId); + } + + uint256 currentTimepoint = clock(); + + if (snapshot >= currentTimepoint) { + return ProposalState.Pending; + } + + uint256 deadline = proposalDeadline(proposalId); + + if (deadline >= currentTimepoint) { + return ProposalState.Active; + } else if (!_quorumReached(proposalId) || !_voteSucceeded(proposalId)) { + return ProposalState.Defeated; + } else if (proposalEta(proposalId) == 0) { + return ProposalState.Succeeded; + } else { + return ProposalState.Queued; + } + } + + /// @inheritdoc IGovernor + function proposalThreshold() public view virtual returns (uint256) { + return 0; + } + + /// @inheritdoc IGovernor + function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256) { + return _proposals[proposalId].voteStart; + } + + /// @inheritdoc IGovernor + function proposalDeadline(uint256 proposalId) public view virtual returns (uint256) { + return _proposals[proposalId].voteStart + _proposals[proposalId].voteDuration; + } + + /// @inheritdoc IGovernor + function proposalProposer(uint256 proposalId) public view virtual returns (address) { + return _proposals[proposalId].proposer; + } + + /// @inheritdoc IGovernor + function proposalEta(uint256 proposalId) public view virtual returns (uint256) { + return _proposals[proposalId].etaSeconds; + } + + /// @inheritdoc IGovernor + function proposalNeedsQueuing(uint256) public view virtual returns (bool) { + return false; + } + + /** + * @dev Reverts if the `msg.sender` is not the executor. In case the executor is not this contract + * itself, the function reverts if `msg.data` is not whitelisted as a result of an {execute} + * operation. See {onlyGovernance}. + */ + function _checkGovernance() internal virtual { + if (_executor() != _msgSender()) { + revert GovernorOnlyExecutor(_msgSender()); + } + if (_executor() != address(this)) { + bytes32 msgDataHash = keccak256(_msgData()); + // loop until popping the expected operation - throw if deque is empty (operation not authorized) + while (_governanceCall.popFront() != msgDataHash) {} + } + } + + /** + * @dev Amount of votes already cast passes the threshold limit. + */ + function _quorumReached(uint256 proposalId) internal view virtual returns (bool); + + /** + * @dev Is the proposal successful or not. + */ + function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool); + + /** + * @dev Get the voting weight of `account` at a specific `timepoint`, for a vote as described by `params`. + */ + function _getVotes(address account, uint256 timepoint, bytes memory params) internal view virtual returns (uint256); + + /** + * @dev Register a vote for `proposalId` by `account` with a given `support`, voting `weight` and voting `params`. + * + * Note: Support is generic and can represent various things depending on the voting system used. + */ + function _countVote( + uint256 proposalId, + address account, + uint8 support, + uint256 totalWeight, + bytes memory params + ) internal virtual returns (uint256); + + /** + * @dev Hook that should be called every time the tally for a proposal is updated. + * + * Note: This function must run successfully. Reverts will result in the bricking of governance + */ + function _tallyUpdated(uint256 proposalId) internal virtual {} + + /** + * @dev Default additional encoded parameters used by castVote methods that don't include them + * + * Note: Should be overridden by specific implementations to use an appropriate value, the + * meaning of the additional params, in the context of that implementation + */ + function _defaultParams() internal view virtual returns (bytes memory) { + return ""; + } + + /** + * @dev See {IGovernor-propose}. This function has opt-in frontrunning protection, described in {_isValidDescriptionForProposer}. + */ + function propose( + address[] memory targets, + uint256[] memory values, + bytes[] memory calldatas, + string memory description + ) public virtual returns (uint256) { + address proposer = _msgSender(); + + // check description restriction + if (!_isValidDescriptionForProposer(proposer, description)) { + revert GovernorRestrictedProposer(proposer); + } + + // check proposal threshold + uint256 votesThreshold = proposalThreshold(); + if (votesThreshold > 0) { + uint256 proposerVotes = getVotes(proposer, clock() - 1); + if (proposerVotes < votesThreshold) { + revert GovernorInsufficientProposerVotes(proposer, proposerVotes, votesThreshold); + } + } + + return _propose(targets, values, calldatas, description, proposer); + } + + /** + * @dev Internal propose mechanism. Can be overridden to add more logic on proposal creation. + * + * Emits a {IGovernor-ProposalCreated} event. + */ + function _propose( + address[] memory targets, + uint256[] memory values, + bytes[] memory calldatas, + string memory description, + address proposer + ) internal virtual returns (uint256 proposalId) { + proposalId = getProposalId(targets, values, calldatas, keccak256(bytes(description))); + + if (targets.length != values.length || targets.length != calldatas.length || targets.length == 0) { + revert GovernorInvalidProposalLength(targets.length, calldatas.length, values.length); + } + if (_proposals[proposalId].voteStart != 0) { + revert GovernorUnexpectedProposalState(proposalId, state(proposalId), bytes32(0)); + } + + uint256 snapshot = clock() + votingDelay(); + uint256 duration = votingPeriod(); + + ProposalCore storage proposal = _proposals[proposalId]; + proposal.proposer = proposer; + proposal.voteStart = SafeCast.toUint48(snapshot); + proposal.voteDuration = SafeCast.toUint32(duration); + + emit ProposalCreated( + proposalId, + proposer, + targets, + values, + new string[](targets.length), + calldatas, + snapshot, + snapshot + duration, + description + ); + + // Using a named return variable to avoid stack too deep errors + } + + /// @inheritdoc IGovernor + function queue( + address[] memory targets, + uint256[] memory values, + bytes[] memory calldatas, + bytes32 descriptionHash + ) public virtual returns (uint256) { + uint256 proposalId = getProposalId(targets, values, calldatas, descriptionHash); + + _validateStateBitmap(proposalId, _encodeStateBitmap(ProposalState.Succeeded)); + + uint48 etaSeconds = _queueOperations(proposalId, targets, values, calldatas, descriptionHash); + + if (etaSeconds != 0) { + _proposals[proposalId].etaSeconds = etaSeconds; + emit ProposalQueued(proposalId, etaSeconds); + } else { + revert GovernorQueueNotImplemented(); + } + + return proposalId; + } + + /** + * @dev Internal queuing mechanism. Can be overridden (without a super call) to modify the way queuing is + * performed (for example adding a vault/timelock). + * + * This is empty by default, and must be overridden to implement queuing. + * + * This function returns a timestamp that describes the expected ETA for execution. If the returned value is 0 + * (which is the default value), the core will consider queueing did not succeed, and the public {queue} function + * will revert. + * + * NOTE: Calling this function directly will NOT check the current state of the proposal, or emit the + * `ProposalQueued` event. Queuing a proposal should be done using {queue}. + */ + function _queueOperations( + uint256 /*proposalId*/, + address[] memory /*targets*/, + uint256[] memory /*values*/, + bytes[] memory /*calldatas*/, + bytes32 /*descriptionHash*/ + ) internal virtual returns (uint48) { + return 0; + } + + /// @inheritdoc IGovernor + function execute( + address[] memory targets, + uint256[] memory values, + bytes[] memory calldatas, + bytes32 descriptionHash + ) public payable virtual returns (uint256) { + uint256 proposalId = getProposalId(targets, values, calldatas, descriptionHash); + + _validateStateBitmap( + proposalId, + _encodeStateBitmap(ProposalState.Succeeded) | _encodeStateBitmap(ProposalState.Queued) + ); + + // mark as executed before calls to avoid reentrancy + _proposals[proposalId].executed = true; + + // before execute: register governance call in queue. + if (_executor() != address(this)) { + for (uint256 i = 0; i < targets.length; ++i) { + if (targets[i] == address(this)) { + _governanceCall.pushBack(keccak256(calldatas[i])); + } + } + } + + _executeOperations(proposalId, targets, values, calldatas, descriptionHash); + + // after execute: cleanup governance call queue. + if (_executor() != address(this) && !_governanceCall.empty()) { + _governanceCall.clear(); + } + + emit ProposalExecuted(proposalId); + + return proposalId; + } + + /** + * @dev Internal execution mechanism. Can be overridden (without a super call) to modify the way execution is + * performed (for example adding a vault/timelock). + * + * NOTE: Calling this function directly will NOT check the current state of the proposal, set the executed flag to + * true or emit the `ProposalExecuted` event. Executing a proposal should be done using {execute}. + */ + function _executeOperations( + uint256 /* proposalId */, + address[] memory targets, + uint256[] memory values, + bytes[] memory calldatas, + bytes32 /*descriptionHash*/ + ) internal virtual { + for (uint256 i = 0; i < targets.length; ++i) { + (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]); + Address.verifyCallResult(success, returndata); + } + } + + /// @inheritdoc IGovernor + function cancel( + address[] memory targets, + uint256[] memory values, + bytes[] memory calldatas, + bytes32 descriptionHash + ) public virtual returns (uint256) { + // The proposalId will be recomputed in the `_cancel` call further down. However we need the value before we + // do the internal call, because we need to check the proposal state BEFORE the internal `_cancel` call + // changes it. The `getProposalId` duplication has a cost that is limited, and that we accept. + uint256 proposalId = getProposalId(targets, values, calldatas, descriptionHash); + + address caller = _msgSender(); + if (!_validateCancel(proposalId, caller)) revert GovernorUnableToCancel(proposalId, caller); + + return _cancel(targets, values, calldatas, descriptionHash); + } + + /** + * @dev Internal cancel mechanism with minimal restrictions. A proposal can be cancelled in any state other than + * Canceled, Expired, or Executed. Once cancelled a proposal can't be re-submitted. + * + * Emits a {IGovernor-ProposalCanceled} event. + */ + function _cancel( + address[] memory targets, + uint256[] memory values, + bytes[] memory calldatas, + bytes32 descriptionHash + ) internal virtual returns (uint256) { + uint256 proposalId = getProposalId(targets, values, calldatas, descriptionHash); + + _validateStateBitmap( + proposalId, + ALL_PROPOSAL_STATES_BITMAP ^ + _encodeStateBitmap(ProposalState.Canceled) ^ + _encodeStateBitmap(ProposalState.Expired) ^ + _encodeStateBitmap(ProposalState.Executed) + ); + + _proposals[proposalId].canceled = true; + emit ProposalCanceled(proposalId); + + return proposalId; + } + + /// @inheritdoc IGovernor + function getVotes(address account, uint256 timepoint) public view virtual returns (uint256) { + return _getVotes(account, timepoint, _defaultParams()); + } + + /// @inheritdoc IGovernor + function getVotesWithParams( + address account, + uint256 timepoint, + bytes memory params + ) public view virtual returns (uint256) { + return _getVotes(account, timepoint, params); + } + + /// @inheritdoc IGovernor + function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256) { + address voter = _msgSender(); + return _castVote(proposalId, voter, support, ""); + } + + /// @inheritdoc IGovernor + function castVoteWithReason( + uint256 proposalId, + uint8 support, + string calldata reason + ) public virtual returns (uint256) { + address voter = _msgSender(); + return _castVote(proposalId, voter, support, reason); + } + + /// @inheritdoc IGovernor + function castVoteWithReasonAndParams( + uint256 proposalId, + uint8 support, + string calldata reason, + bytes memory params + ) public virtual returns (uint256) { + address voter = _msgSender(); + return _castVote(proposalId, voter, support, reason, params); + } + + /// @inheritdoc IGovernor + function castVoteBySig( + uint256 proposalId, + uint8 support, + address voter, + bytes memory signature + ) public virtual returns (uint256) { + if (!_validateVoteSig(proposalId, support, voter, signature)) { + revert GovernorInvalidSignature(voter); + } + return _castVote(proposalId, voter, support, ""); + } + + /// @inheritdoc IGovernor + function castVoteWithReasonAndParamsBySig( + uint256 proposalId, + uint8 support, + address voter, + string calldata reason, + bytes memory params, + bytes memory signature + ) public virtual returns (uint256) { + if (!_validateExtendedVoteSig(proposalId, support, voter, reason, params, signature)) { + revert GovernorInvalidSignature(voter); + } + return _castVote(proposalId, voter, support, reason, params); + } + + /// @dev Validate the `signature` used in {castVoteBySig} function. + function _validateVoteSig( + uint256 proposalId, + uint8 support, + address voter, + bytes memory signature + ) internal virtual returns (bool) { + return + SignatureChecker.isValidSignatureNow( + voter, + _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support, voter, _useNonce(voter)))), + signature + ); + } + + /// @dev Validate the `signature` used in {castVoteWithReasonAndParamsBySig} function. + function _validateExtendedVoteSig( + uint256 proposalId, + uint8 support, + address voter, + string memory reason, + bytes memory params, + bytes memory signature + ) internal virtual returns (bool) { + return + SignatureChecker.isValidSignatureNow( + voter, + _hashTypedDataV4( + keccak256( + abi.encode( + EXTENDED_BALLOT_TYPEHASH, + proposalId, + support, + voter, + _useNonce(voter), + keccak256(bytes(reason)), + keccak256(params) + ) + ) + ), + signature + ); + } + + /** + * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve + * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams(). + * + * Emits a {IGovernor-VoteCast} event. + */ + function _castVote( + uint256 proposalId, + address account, + uint8 support, + string memory reason + ) internal virtual returns (uint256) { + return _castVote(proposalId, account, support, reason, _defaultParams()); + } + + /** + * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve + * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. + * + * Emits a {IGovernor-VoteCast} event. + */ + function _castVote( + uint256 proposalId, + address account, + uint8 support, + string memory reason, + bytes memory params + ) internal virtual returns (uint256) { + _validateStateBitmap(proposalId, _encodeStateBitmap(ProposalState.Active)); + + uint256 totalWeight = _getVotes(account, proposalSnapshot(proposalId), params); + uint256 votedWeight = _countVote(proposalId, account, support, totalWeight, params); + + if (params.length == 0) { + emit VoteCast(account, proposalId, support, votedWeight, reason); + } else { + emit VoteCastWithParams(account, proposalId, support, votedWeight, reason, params); + } + + _tallyUpdated(proposalId); + + return votedWeight; + } + + /** + * @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor + * is some contract other than the governor itself, like when using a timelock, this function can be invoked + * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake. + * Note that if the executor is simply the governor itself, use of `relay` is redundant. + */ + function relay(address target, uint256 value, bytes calldata data) external payable virtual onlyGovernance { + (bool success, bytes memory returndata) = target.call{value: value}(data); + Address.verifyCallResult(success, returndata); + } + + /** + * @dev Address through which the governor executes action. Will be overloaded by module that execute actions + * through another contract such as a timelock. + */ + function _executor() internal view virtual returns (address) { + return address(this); + } + + /** + * @dev See {IERC721Receiver-onERC721Received}. + * Receiving tokens is disabled if the governance executor is other than the governor itself (eg. when using with a timelock). + */ + function onERC721Received(address, address, uint256, bytes memory) public virtual returns (bytes4) { + if (_executor() != address(this)) { + revert GovernorDisabledDeposit(); + } + return this.onERC721Received.selector; + } + + /** + * @dev See {IERC1155Receiver-onERC1155Received}. + * Receiving tokens is disabled if the governance executor is other than the governor itself (eg. when using with a timelock). + */ + function onERC1155Received(address, address, uint256, uint256, bytes memory) public virtual returns (bytes4) { + if (_executor() != address(this)) { + revert GovernorDisabledDeposit(); + } + return this.onERC1155Received.selector; + } + + /** + * @dev See {IERC1155Receiver-onERC1155BatchReceived}. + * Receiving tokens is disabled if the governance executor is other than the governor itself (eg. when using with a timelock). + */ + function onERC1155BatchReceived( + address, + address, + uint256[] memory, + uint256[] memory, + bytes memory + ) public virtual returns (bytes4) { + if (_executor() != address(this)) { + revert GovernorDisabledDeposit(); + } + return this.onERC1155BatchReceived.selector; + } + + /** + * @dev Encodes a `ProposalState` into a `bytes32` representation where each bit enabled corresponds to + * the underlying position in the `ProposalState` enum. For example: + * + * 0x000...10000 + * ^^^^^^------ ... + * ^----- Succeeded + * ^---- Defeated + * ^--- Canceled + * ^-- Active + * ^- Pending + */ + function _encodeStateBitmap(ProposalState proposalState) internal pure returns (bytes32) { + return bytes32(1 << uint8(proposalState)); + } + + /** + * @dev Check that the current state of a proposal matches the requirements described by the `allowedStates` bitmap. + * This bitmap should be built using `_encodeStateBitmap`. + * + * If requirements are not met, reverts with a {GovernorUnexpectedProposalState} error. + */ + function _validateStateBitmap(uint256 proposalId, bytes32 allowedStates) internal view returns (ProposalState) { + ProposalState currentState = state(proposalId); + if (_encodeStateBitmap(currentState) & allowedStates == bytes32(0)) { + revert GovernorUnexpectedProposalState(proposalId, currentState, allowedStates); + } + return currentState; + } + + /* + * @dev Check if the proposer is authorized to submit a proposal with the given description. + * + * If the proposal description ends with `#proposer=0x???`, where `0x???` is an address written as a hex string + * (case insensitive), then the submission of this proposal will only be authorized to said address. + * + * This is used for frontrunning protection. By adding this pattern at the end of their proposal, one can ensure + * that no other address can submit the same proposal. An attacker would have to either remove or change that part, + * which would result in a different proposal id. + * + * If the description does not match this pattern, it is unrestricted and anyone can submit it. This includes: + * - If the `0x???` part is not a valid hex string. + * - If the `0x???` part is a valid hex string, but does not contain exactly 40 hex digits. + * - If it ends with the expected suffix followed by newlines or other whitespace. + * - If it ends with some other similar suffix, e.g. `#other=abc`. + * - If it does not end with any such suffix. + */ + function _isValidDescriptionForProposer( + address proposer, + string memory description + ) internal view virtual returns (bool) { + unchecked { + uint256 length = bytes(description).length; + + // Length is too short to contain a valid proposer suffix + if (length < 52) { + return true; + } + + // Extract what would be the `#proposer=` marker beginning the suffix + bytes10 marker = bytes10(_unsafeReadBytesOffset(bytes(description), length - 52)); + + // If the marker is not found, there is no proposer suffix to check + if (marker != bytes10("#proposer=")) { + return true; + } + + // Check that the last 42 characters (after the marker) are a properly formatted address. + (bool success, address recovered) = Strings.tryParseAddress(description, length - 42, length); + return !success || recovered == proposer; + } + } + + /** + * @dev Check if the `caller` can cancel the proposal with the given `proposalId`. + * + * The default implementation allows the proposal proposer to cancel the proposal during the pending state. + */ + function _validateCancel(uint256 proposalId, address caller) internal view virtual returns (bool) { + return (state(proposalId) == ProposalState.Pending) && caller == proposalProposer(proposalId); + } + + /// @inheritdoc IERC6372 + function clock() public view virtual returns (uint48); + + /// @inheritdoc IERC6372 + // solhint-disable-next-line func-name-mixedcase + function CLOCK_MODE() public view virtual returns (string memory); + + /// @inheritdoc IGovernor + function votingDelay() public view virtual returns (uint256); + + /// @inheritdoc IGovernor + function votingPeriod() public view virtual returns (uint256); + + /// @inheritdoc IGovernor + function quorum(uint256 timepoint) public view virtual returns (uint256); + + /** + * @dev Reads a bytes32 from a bytes array without bounds checking. + * + * NOTE: making this function internal would mean it could be used with memory unsafe offset, and marking the + * assembly block as such would prevent some optimizations. + */ + function _unsafeReadBytesOffset(bytes memory buffer, uint256 offset) private pure returns (bytes32 value) { + // This is not memory safe in the general case, but all calls to this private function are within bounds. + assembly ("memory-safe") { + value := mload(add(add(buffer, 0x20), offset)) + } + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/governance/IGovernor.sol b/dependencies/@openzeppelin-contracts-5.4.0/governance/IGovernor.sol new file mode 100644 index 00000000..b3f0feb9 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/governance/IGovernor.sol @@ -0,0 +1,454 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (governance/IGovernor.sol) + +pragma solidity >=0.8.4; + +import {IERC165} from "../interfaces/IERC165.sol"; +import {IERC6372} from "../interfaces/IERC6372.sol"; + +/** + * @dev Interface of the {Governor} core. + * + * NOTE: Event parameters lack the `indexed` keyword for compatibility with GovernorBravo events. + * Making event parameters `indexed` affects how events are decoded, potentially breaking existing indexers. + */ +interface IGovernor is IERC165, IERC6372 { + enum ProposalState { + Pending, + Active, + Canceled, + Defeated, + Succeeded, + Queued, + Expired, + Executed + } + + /** + * @dev Empty proposal or a mismatch between the parameters length for a proposal call. + */ + error GovernorInvalidProposalLength(uint256 targets, uint256 calldatas, uint256 values); + + /** + * @dev The vote was already cast. + */ + error GovernorAlreadyCastVote(address voter); + + /** + * @dev Token deposits are disabled in this contract. + */ + error GovernorDisabledDeposit(); + + /** + * @dev The `account` is not the governance executor. + */ + error GovernorOnlyExecutor(address account); + + /** + * @dev The `proposalId` doesn't exist. + */ + error GovernorNonexistentProposal(uint256 proposalId); + + /** + * @dev The current state of a proposal is not the required for performing an operation. + * The `expectedStates` is a bitmap with the bits enabled for each ProposalState enum position + * counting from right to left. + * + * NOTE: If `expectedState` is `bytes32(0)`, the proposal is expected to not be in any state (i.e. not exist). + * This is the case when a proposal that is expected to be unset is already initiated (the proposal is duplicated). + * + * See {Governor-_encodeStateBitmap}. + */ + error GovernorUnexpectedProposalState(uint256 proposalId, ProposalState current, bytes32 expectedStates); + + /** + * @dev The voting period set is not a valid period. + */ + error GovernorInvalidVotingPeriod(uint256 votingPeriod); + + /** + * @dev The `proposer` does not have the required votes to create a proposal. + */ + error GovernorInsufficientProposerVotes(address proposer, uint256 votes, uint256 threshold); + + /** + * @dev The `proposer` is not allowed to create a proposal. + */ + error GovernorRestrictedProposer(address proposer); + + /** + * @dev The vote type used is not valid for the corresponding counting module. + */ + error GovernorInvalidVoteType(); + + /** + * @dev The provided params buffer is not supported by the counting module. + */ + error GovernorInvalidVoteParams(); + + /** + * @dev Queue operation is not implemented for this governor. Execute should be called directly. + */ + error GovernorQueueNotImplemented(); + + /** + * @dev The proposal hasn't been queued yet. + */ + error GovernorNotQueuedProposal(uint256 proposalId); + + /** + * @dev The proposal has already been queued. + */ + error GovernorAlreadyQueuedProposal(uint256 proposalId); + + /** + * @dev The provided signature is not valid for the expected `voter`. + * If the `voter` is a contract, the signature is not valid using {IERC1271-isValidSignature}. + */ + error GovernorInvalidSignature(address voter); + + /** + * @dev The given `account` is unable to cancel the proposal with given `proposalId`. + */ + error GovernorUnableToCancel(uint256 proposalId, address account); + + /** + * @dev Emitted when a proposal is created. + */ + event ProposalCreated( + uint256 proposalId, + address proposer, + address[] targets, + uint256[] values, + string[] signatures, + bytes[] calldatas, + uint256 voteStart, + uint256 voteEnd, + string description + ); + + /** + * @dev Emitted when a proposal is queued. + */ + event ProposalQueued(uint256 proposalId, uint256 etaSeconds); + + /** + * @dev Emitted when a proposal is executed. + */ + event ProposalExecuted(uint256 proposalId); + + /** + * @dev Emitted when a proposal is canceled. + */ + event ProposalCanceled(uint256 proposalId); + + /** + * @dev Emitted when a vote is cast without params. + * + * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used. + */ + event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason); + + /** + * @dev Emitted when a vote is cast with params. + * + * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used. + * `params` are additional encoded parameters. Their interpretation also depends on the voting module used. + */ + event VoteCastWithParams( + address indexed voter, + uint256 proposalId, + uint8 support, + uint256 weight, + string reason, + bytes params + ); + + /** + * @notice module:core + * @dev Name of the governor instance (used in building the EIP-712 domain separator). + */ + function name() external view returns (string memory); + + /** + * @notice module:core + * @dev Version of the governor instance (used in building the EIP-712 domain separator). Default: "1" + */ + function version() external view returns (string memory); + + /** + * @notice module:voting + * @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to + * be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of + * key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`. + * + * There are 2 standard keys: `support` and `quorum`. + * + * - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`. + * - `quorum=bravo` means that only For votes are counted towards quorum. + * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum. + * + * If a counting module makes use of encoded `params`, it should include this under a `params` key with a unique + * name that describes the behavior. For example: + * + * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain. + * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote. + * + * NOTE: The string can be decoded by the standard + * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`] + * JavaScript class. + */ + // solhint-disable-next-line func-name-mixedcase + function COUNTING_MODE() external view returns (string memory); + + /** + * @notice module:core + * @dev Hashing function used to (re)build the proposal id from the proposal details. + * + * NOTE: For all off-chain and external calls, use {getProposalId}. + */ + function hashProposal( + address[] memory targets, + uint256[] memory values, + bytes[] memory calldatas, + bytes32 descriptionHash + ) external pure returns (uint256); + + /** + * @notice module:core + * @dev Function used to get the proposal id from the proposal details. + */ + function getProposalId( + address[] memory targets, + uint256[] memory values, + bytes[] memory calldatas, + bytes32 descriptionHash + ) external view returns (uint256); + + /** + * @notice module:core + * @dev Current state of a proposal, following Compound's convention + */ + function state(uint256 proposalId) external view returns (ProposalState); + + /** + * @notice module:core + * @dev The number of votes required in order for a voter to become a proposer. + */ + function proposalThreshold() external view returns (uint256); + + /** + * @notice module:core + * @dev Timepoint used to retrieve user's votes and quorum. If using block number (as per Compound's Comp), the + * snapshot is performed at the end of this block. Hence, voting for this proposal starts at the beginning of the + * following block. + */ + function proposalSnapshot(uint256 proposalId) external view returns (uint256); + + /** + * @notice module:core + * @dev Timepoint at which votes close. If using block number, votes close at the end of this block, so it is + * possible to cast a vote during this block. + */ + function proposalDeadline(uint256 proposalId) external view returns (uint256); + + /** + * @notice module:core + * @dev The account that created a proposal. + */ + function proposalProposer(uint256 proposalId) external view returns (address); + + /** + * @notice module:core + * @dev The time when a queued proposal becomes executable ("ETA"). Unlike {proposalSnapshot} and + * {proposalDeadline}, this doesn't use the governor clock, and instead relies on the executor's clock which may be + * different. In most cases this will be a timestamp. + */ + function proposalEta(uint256 proposalId) external view returns (uint256); + + /** + * @notice module:core + * @dev Whether a proposal needs to be queued before execution. + */ + function proposalNeedsQueuing(uint256 proposalId) external view returns (bool); + + /** + * @notice module:user-config + * @dev Delay, between the proposal is created and the vote starts. The unit this duration is expressed in depends + * on the clock (see ERC-6372) this contract uses. + * + * This can be increased to leave time for users to buy voting power, or delegate it, before the voting of a + * proposal starts. + * + * NOTE: While this interface returns a uint256, timepoints are stored as uint48 following the ERC-6372 clock type. + * Consequently this value must fit in a uint48 (when added to the current clock). See {IERC6372-clock}. + */ + function votingDelay() external view returns (uint256); + + /** + * @notice module:user-config + * @dev Delay between the vote start and vote end. The unit this duration is expressed in depends on the clock + * (see ERC-6372) this contract uses. + * + * NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting + * duration compared to the voting delay. + * + * NOTE: This value is stored when the proposal is submitted so that possible changes to the value do not affect + * proposals that have already been submitted. The type used to save it is a uint32. Consequently, while this + * interface returns a uint256, the value it returns should fit in a uint32. + */ + function votingPeriod() external view returns (uint256); + + /** + * @notice module:user-config + * @dev Minimum number of cast voted required for a proposal to be successful. + * + * NOTE: The `timepoint` parameter corresponds to the snapshot used for counting vote. This allows to scale the + * quorum depending on values such as the totalSupply of a token at this timepoint (see {ERC20Votes}). + */ + function quorum(uint256 timepoint) external view returns (uint256); + + /** + * @notice module:reputation + * @dev Voting power of an `account` at a specific `timepoint`. + * + * Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or + * multiple), {ERC20Votes} tokens. + */ + function getVotes(address account, uint256 timepoint) external view returns (uint256); + + /** + * @notice module:reputation + * @dev Voting power of an `account` at a specific `timepoint` given additional encoded parameters. + */ + function getVotesWithParams( + address account, + uint256 timepoint, + bytes memory params + ) external view returns (uint256); + + /** + * @notice module:voting + * @dev Returns whether `account` has cast a vote on `proposalId`. + */ + function hasVoted(uint256 proposalId, address account) external view returns (bool); + + /** + * @dev Create a new proposal. Vote start after a delay specified by {IGovernor-votingDelay} and lasts for a + * duration specified by {IGovernor-votingPeriod}. + * + * Emits a {ProposalCreated} event. + * + * NOTE: The state of the Governor and `targets` may change between the proposal creation and its execution. + * This may be the result of third party actions on the targeted contracts, or other governor proposals. + * For example, the balance of this contract could be updated or its access control permissions may be modified, + * possibly compromising the proposal's ability to execute successfully (e.g. the governor doesn't have enough + * value to cover a proposal with multiple transfers). + */ + function propose( + address[] memory targets, + uint256[] memory values, + bytes[] memory calldatas, + string memory description + ) external returns (uint256 proposalId); + + /** + * @dev Queue a proposal. Some governors require this step to be performed before execution can happen. If queuing + * is not necessary, this function may revert. + * Queuing a proposal requires the quorum to be reached, the vote to be successful, and the deadline to be reached. + * + * Emits a {ProposalQueued} event. + */ + function queue( + address[] memory targets, + uint256[] memory values, + bytes[] memory calldatas, + bytes32 descriptionHash + ) external returns (uint256 proposalId); + + /** + * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the + * deadline to be reached. Depending on the governor it might also be required that the proposal was queued and + * that some delay passed. + * + * Emits a {ProposalExecuted} event. + * + * NOTE: Some modules can modify the requirements for execution, for example by adding an additional timelock. + */ + function execute( + address[] memory targets, + uint256[] memory values, + bytes[] memory calldatas, + bytes32 descriptionHash + ) external payable returns (uint256 proposalId); + + /** + * @dev Cancel a proposal. A proposal is cancellable by the proposer, but only while it is Pending state, i.e. + * before the vote starts. + * + * Emits a {ProposalCanceled} event. + */ + function cancel( + address[] memory targets, + uint256[] memory values, + bytes[] memory calldatas, + bytes32 descriptionHash + ) external returns (uint256 proposalId); + + /** + * @dev Cast a vote + * + * Emits a {VoteCast} event. + */ + function castVote(uint256 proposalId, uint8 support) external returns (uint256 balance); + + /** + * @dev Cast a vote with a reason + * + * Emits a {VoteCast} event. + */ + function castVoteWithReason( + uint256 proposalId, + uint8 support, + string calldata reason + ) external returns (uint256 balance); + + /** + * @dev Cast a vote with a reason and additional encoded parameters + * + * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params. + */ + function castVoteWithReasonAndParams( + uint256 proposalId, + uint8 support, + string calldata reason, + bytes memory params + ) external returns (uint256 balance); + + /** + * @dev Cast a vote using the voter's signature, including ERC-1271 signature support. + * + * Emits a {VoteCast} event. + */ + function castVoteBySig( + uint256 proposalId, + uint8 support, + address voter, + bytes memory signature + ) external returns (uint256 balance); + + /** + * @dev Cast a vote with a reason and additional encoded parameters using the voter's signature, + * including ERC-1271 signature support. + * + * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params. + */ + function castVoteWithReasonAndParamsBySig( + uint256 proposalId, + uint8 support, + address voter, + string calldata reason, + bytes memory params, + bytes memory signature + ) external returns (uint256 balance); +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/governance/TimelockController.sol b/dependencies/@openzeppelin-contracts-5.4.0/governance/TimelockController.sol new file mode 100644 index 00000000..17fef921 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/governance/TimelockController.sol @@ -0,0 +1,471 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (governance/TimelockController.sol) + +pragma solidity ^0.8.20; + +import {AccessControl} from "../access/AccessControl.sol"; +import {ERC721Holder} from "../token/ERC721/utils/ERC721Holder.sol"; +import {ERC1155Holder} from "../token/ERC1155/utils/ERC1155Holder.sol"; +import {Address} from "../utils/Address.sol"; +import {IERC165} from "../utils/introspection/ERC165.sol"; + +/** + * @dev Contract module which acts as a timelocked controller. When set as the + * owner of an `Ownable` smart contract, it enforces a timelock on all + * `onlyOwner` maintenance operations. This gives time for users of the + * controlled contract to exit before a potentially dangerous maintenance + * operation is applied. + * + * By default, this contract is self administered, meaning administration tasks + * have to go through the timelock process. The proposer (resp executor) role + * is in charge of proposing (resp executing) operations. A common use case is + * to position this {TimelockController} as the owner of a smart contract, with + * a multisig or a DAO as the sole proposer. + */ +contract TimelockController is AccessControl, ERC721Holder, ERC1155Holder { + bytes32 public constant PROPOSER_ROLE = keccak256("PROPOSER_ROLE"); + bytes32 public constant EXECUTOR_ROLE = keccak256("EXECUTOR_ROLE"); + bytes32 public constant CANCELLER_ROLE = keccak256("CANCELLER_ROLE"); + uint256 internal constant _DONE_TIMESTAMP = uint256(1); + + mapping(bytes32 id => uint256) private _timestamps; + uint256 private _minDelay; + + enum OperationState { + Unset, + Waiting, + Ready, + Done + } + + /** + * @dev Mismatch between the parameters length for an operation call. + */ + error TimelockInvalidOperationLength(uint256 targets, uint256 payloads, uint256 values); + + /** + * @dev The schedule operation doesn't meet the minimum delay. + */ + error TimelockInsufficientDelay(uint256 delay, uint256 minDelay); + + /** + * @dev The current state of an operation is not as required. + * The `expectedStates` is a bitmap with the bits enabled for each OperationState enum position + * counting from right to left. + * + * See {_encodeStateBitmap}. + */ + error TimelockUnexpectedOperationState(bytes32 operationId, bytes32 expectedStates); + + /** + * @dev The predecessor to an operation not yet done. + */ + error TimelockUnexecutedPredecessor(bytes32 predecessorId); + + /** + * @dev The caller account is not authorized. + */ + error TimelockUnauthorizedCaller(address caller); + + /** + * @dev Emitted when a call is scheduled as part of operation `id`. + */ + event CallScheduled( + bytes32 indexed id, + uint256 indexed index, + address target, + uint256 value, + bytes data, + bytes32 predecessor, + uint256 delay + ); + + /** + * @dev Emitted when a call is performed as part of operation `id`. + */ + event CallExecuted(bytes32 indexed id, uint256 indexed index, address target, uint256 value, bytes data); + + /** + * @dev Emitted when new proposal is scheduled with non-zero salt. + */ + event CallSalt(bytes32 indexed id, bytes32 salt); + + /** + * @dev Emitted when operation `id` is cancelled. + */ + event Cancelled(bytes32 indexed id); + + /** + * @dev Emitted when the minimum delay for future operations is modified. + */ + event MinDelayChange(uint256 oldDuration, uint256 newDuration); + + /** + * @dev Initializes the contract with the following parameters: + * + * - `minDelay`: initial minimum delay in seconds for operations + * - `proposers`: accounts to be granted proposer and canceller roles + * - `executors`: accounts to be granted executor role + * - `admin`: optional account to be granted admin role; disable with zero address + * + * IMPORTANT: The optional admin can aid with initial configuration of roles after deployment + * without being subject to delay, but this role should be subsequently renounced in favor of + * administration through timelocked proposals. Previous versions of this contract would assign + * this admin to the deployer automatically and should be renounced as well. + */ + constructor(uint256 minDelay, address[] memory proposers, address[] memory executors, address admin) { + // self administration + _grantRole(DEFAULT_ADMIN_ROLE, address(this)); + + // optional admin + if (admin != address(0)) { + _grantRole(DEFAULT_ADMIN_ROLE, admin); + } + + // register proposers and cancellers + for (uint256 i = 0; i < proposers.length; ++i) { + _grantRole(PROPOSER_ROLE, proposers[i]); + _grantRole(CANCELLER_ROLE, proposers[i]); + } + + // register executors + for (uint256 i = 0; i < executors.length; ++i) { + _grantRole(EXECUTOR_ROLE, executors[i]); + } + + _minDelay = minDelay; + emit MinDelayChange(0, minDelay); + } + + /** + * @dev Modifier to make a function callable only by a certain role. In + * addition to checking the sender's role, `address(0)` 's role is also + * considered. Granting a role to `address(0)` is equivalent to enabling + * this role for everyone. + */ + modifier onlyRoleOrOpenRole(bytes32 role) { + if (!hasRole(role, address(0))) { + _checkRole(role, _msgSender()); + } + _; + } + + /** + * @dev Contract might receive/hold ETH as part of the maintenance process. + */ + receive() external payable virtual {} + + /// @inheritdoc IERC165 + function supportsInterface( + bytes4 interfaceId + ) public view virtual override(AccessControl, ERC1155Holder) returns (bool) { + return super.supportsInterface(interfaceId); + } + + /** + * @dev Returns whether an id corresponds to a registered operation. This + * includes both Waiting, Ready, and Done operations. + */ + function isOperation(bytes32 id) public view returns (bool) { + return getOperationState(id) != OperationState.Unset; + } + + /** + * @dev Returns whether an operation is pending or not. Note that a "pending" operation may also be "ready". + */ + function isOperationPending(bytes32 id) public view returns (bool) { + OperationState state = getOperationState(id); + return state == OperationState.Waiting || state == OperationState.Ready; + } + + /** + * @dev Returns whether an operation is ready for execution. Note that a "ready" operation is also "pending". + */ + function isOperationReady(bytes32 id) public view returns (bool) { + return getOperationState(id) == OperationState.Ready; + } + + /** + * @dev Returns whether an operation is done or not. + */ + function isOperationDone(bytes32 id) public view returns (bool) { + return getOperationState(id) == OperationState.Done; + } + + /** + * @dev Returns the timestamp at which an operation becomes ready (0 for + * unset operations, 1 for done operations). + */ + function getTimestamp(bytes32 id) public view virtual returns (uint256) { + return _timestamps[id]; + } + + /** + * @dev Returns operation state. + */ + function getOperationState(bytes32 id) public view virtual returns (OperationState) { + uint256 timestamp = getTimestamp(id); + if (timestamp == 0) { + return OperationState.Unset; + } else if (timestamp == _DONE_TIMESTAMP) { + return OperationState.Done; + } else if (timestamp > block.timestamp) { + return OperationState.Waiting; + } else { + return OperationState.Ready; + } + } + + /** + * @dev Returns the minimum delay in seconds for an operation to become valid. + * + * This value can be changed by executing an operation that calls `updateDelay`. + */ + function getMinDelay() public view virtual returns (uint256) { + return _minDelay; + } + + /** + * @dev Returns the identifier of an operation containing a single + * transaction. + */ + function hashOperation( + address target, + uint256 value, + bytes calldata data, + bytes32 predecessor, + bytes32 salt + ) public pure virtual returns (bytes32) { + return keccak256(abi.encode(target, value, data, predecessor, salt)); + } + + /** + * @dev Returns the identifier of an operation containing a batch of + * transactions. + */ + function hashOperationBatch( + address[] calldata targets, + uint256[] calldata values, + bytes[] calldata payloads, + bytes32 predecessor, + bytes32 salt + ) public pure virtual returns (bytes32) { + return keccak256(abi.encode(targets, values, payloads, predecessor, salt)); + } + + /** + * @dev Schedule an operation containing a single transaction. + * + * Emits {CallSalt} if salt is nonzero, and {CallScheduled}. + * + * Requirements: + * + * - the caller must have the 'proposer' role. + */ + function schedule( + address target, + uint256 value, + bytes calldata data, + bytes32 predecessor, + bytes32 salt, + uint256 delay + ) public virtual onlyRole(PROPOSER_ROLE) { + bytes32 id = hashOperation(target, value, data, predecessor, salt); + _schedule(id, delay); + emit CallScheduled(id, 0, target, value, data, predecessor, delay); + if (salt != bytes32(0)) { + emit CallSalt(id, salt); + } + } + + /** + * @dev Schedule an operation containing a batch of transactions. + * + * Emits {CallSalt} if salt is nonzero, and one {CallScheduled} event per transaction in the batch. + * + * Requirements: + * + * - the caller must have the 'proposer' role. + */ + function scheduleBatch( + address[] calldata targets, + uint256[] calldata values, + bytes[] calldata payloads, + bytes32 predecessor, + bytes32 salt, + uint256 delay + ) public virtual onlyRole(PROPOSER_ROLE) { + if (targets.length != values.length || targets.length != payloads.length) { + revert TimelockInvalidOperationLength(targets.length, payloads.length, values.length); + } + + bytes32 id = hashOperationBatch(targets, values, payloads, predecessor, salt); + _schedule(id, delay); + for (uint256 i = 0; i < targets.length; ++i) { + emit CallScheduled(id, i, targets[i], values[i], payloads[i], predecessor, delay); + } + if (salt != bytes32(0)) { + emit CallSalt(id, salt); + } + } + + /** + * @dev Schedule an operation that is to become valid after a given delay. + */ + function _schedule(bytes32 id, uint256 delay) private { + if (isOperation(id)) { + revert TimelockUnexpectedOperationState(id, _encodeStateBitmap(OperationState.Unset)); + } + uint256 minDelay = getMinDelay(); + if (delay < minDelay) { + revert TimelockInsufficientDelay(delay, minDelay); + } + _timestamps[id] = block.timestamp + delay; + } + + /** + * @dev Cancel an operation. + * + * Requirements: + * + * - the caller must have the 'canceller' role. + */ + function cancel(bytes32 id) public virtual onlyRole(CANCELLER_ROLE) { + if (!isOperationPending(id)) { + revert TimelockUnexpectedOperationState( + id, + _encodeStateBitmap(OperationState.Waiting) | _encodeStateBitmap(OperationState.Ready) + ); + } + delete _timestamps[id]; + + emit Cancelled(id); + } + + /** + * @dev Execute an (ready) operation containing a single transaction. + * + * Emits a {CallExecuted} event. + * + * Requirements: + * + * - the caller must have the 'executor' role. + */ + // This function can reenter, but it doesn't pose a risk because _afterCall checks that the proposal is pending, + // thus any modifications to the operation during reentrancy should be caught. + // slither-disable-next-line reentrancy-eth + function execute( + address target, + uint256 value, + bytes calldata payload, + bytes32 predecessor, + bytes32 salt + ) public payable virtual onlyRoleOrOpenRole(EXECUTOR_ROLE) { + bytes32 id = hashOperation(target, value, payload, predecessor, salt); + + _beforeCall(id, predecessor); + _execute(target, value, payload); + emit CallExecuted(id, 0, target, value, payload); + _afterCall(id); + } + + /** + * @dev Execute an (ready) operation containing a batch of transactions. + * + * Emits one {CallExecuted} event per transaction in the batch. + * + * Requirements: + * + * - the caller must have the 'executor' role. + */ + // This function can reenter, but it doesn't pose a risk because _afterCall checks that the proposal is pending, + // thus any modifications to the operation during reentrancy should be caught. + // slither-disable-next-line reentrancy-eth + function executeBatch( + address[] calldata targets, + uint256[] calldata values, + bytes[] calldata payloads, + bytes32 predecessor, + bytes32 salt + ) public payable virtual onlyRoleOrOpenRole(EXECUTOR_ROLE) { + if (targets.length != values.length || targets.length != payloads.length) { + revert TimelockInvalidOperationLength(targets.length, payloads.length, values.length); + } + + bytes32 id = hashOperationBatch(targets, values, payloads, predecessor, salt); + + _beforeCall(id, predecessor); + for (uint256 i = 0; i < targets.length; ++i) { + address target = targets[i]; + uint256 value = values[i]; + bytes calldata payload = payloads[i]; + _execute(target, value, payload); + emit CallExecuted(id, i, target, value, payload); + } + _afterCall(id); + } + + /** + * @dev Execute an operation's call. + */ + function _execute(address target, uint256 value, bytes calldata data) internal virtual { + (bool success, bytes memory returndata) = target.call{value: value}(data); + Address.verifyCallResult(success, returndata); + } + + /** + * @dev Checks before execution of an operation's calls. + */ + function _beforeCall(bytes32 id, bytes32 predecessor) private view { + if (!isOperationReady(id)) { + revert TimelockUnexpectedOperationState(id, _encodeStateBitmap(OperationState.Ready)); + } + if (predecessor != bytes32(0) && !isOperationDone(predecessor)) { + revert TimelockUnexecutedPredecessor(predecessor); + } + } + + /** + * @dev Checks after execution of an operation's calls. + */ + function _afterCall(bytes32 id) private { + if (!isOperationReady(id)) { + revert TimelockUnexpectedOperationState(id, _encodeStateBitmap(OperationState.Ready)); + } + _timestamps[id] = _DONE_TIMESTAMP; + } + + /** + * @dev Changes the minimum timelock duration for future operations. + * + * Emits a {MinDelayChange} event. + * + * Requirements: + * + * - the caller must be the timelock itself. This can only be achieved by scheduling and later executing + * an operation where the timelock is the target and the data is the ABI-encoded call to this function. + */ + function updateDelay(uint256 newDelay) external virtual { + address sender = _msgSender(); + if (sender != address(this)) { + revert TimelockUnauthorizedCaller(sender); + } + emit MinDelayChange(_minDelay, newDelay); + _minDelay = newDelay; + } + + /** + * @dev Encodes a `OperationState` into a `bytes32` representation where each bit enabled corresponds to + * the underlying position in the `OperationState` enum. For example: + * + * 0x000...1000 + * ^^^^^^----- ... + * ^---- Done + * ^--- Ready + * ^-- Waiting + * ^- Unset + */ + function _encodeStateBitmap(OperationState operationState) internal pure returns (bytes32) { + return bytes32(1 << uint8(operationState)); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/governance/extensions/GovernorCountingFractional.sol b/dependencies/@openzeppelin-contracts-5.4.0/governance/extensions/GovernorCountingFractional.sol new file mode 100644 index 00000000..1460d2dd --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/governance/extensions/GovernorCountingFractional.sol @@ -0,0 +1,190 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (governance/extensions/GovernorCountingFractional.sol) + +pragma solidity ^0.8.24; + +import {IGovernor, Governor} from "../Governor.sol"; +import {GovernorCountingSimple} from "./GovernorCountingSimple.sol"; +import {Math} from "../../utils/math/Math.sol"; + +/** + * @dev Extension of {Governor} for fractional voting. + * + * Similar to {GovernorCountingSimple}, this contract is a votes counting module for {Governor} that supports 3 options: + * Against, For, Abstain. Additionally, it includes a fourth option: Fractional, which allows voters to split their voting + * power amongst the other 3 options. + * + * Votes cast with the Fractional support must be accompanied by a `params` argument that is three packed `uint128` values + * representing the weight the delegate assigns to Against, For, and Abstain respectively. For those votes cast for the other + * 3 options, the `params` argument must be empty. + * + * This is mostly useful when the delegate is a contract that implements its own rules for voting. These delegate-contracts + * can cast fractional votes according to the preferences of multiple entities delegating their voting power. + * + * Some example use cases include: + * + * * Voting from tokens that are held by a DeFi pool + * * Voting from an L2 with tokens held by a bridge + * * Voting privately from a shielded pool using zero knowledge proofs. + * + * Based on ScopeLift's https://github.com/ScopeLift/flexible-voting/blob/e5de2efd1368387b840931f19f3c184c85842761/src/GovernorCountingFractional.sol[`GovernorCountingFractional`] + * + * _Available since v5.1._ + */ +abstract contract GovernorCountingFractional is Governor { + using Math for *; + + uint8 internal constant VOTE_TYPE_FRACTIONAL = 255; + + struct ProposalVote { + uint256 againstVotes; + uint256 forVotes; + uint256 abstainVotes; + mapping(address voter => uint256) usedVotes; + } + + /** + * @dev Mapping from proposal ID to vote tallies for that proposal. + */ + mapping(uint256 proposalId => ProposalVote) private _proposalVotes; + + /** + * @dev A fractional vote params uses more votes than are available for that user. + */ + error GovernorExceedRemainingWeight(address voter, uint256 usedVotes, uint256 remainingWeight); + + /// @inheritdoc IGovernor + // solhint-disable-next-line func-name-mixedcase + function COUNTING_MODE() public pure virtual override returns (string memory) { + return "support=bravo,fractional&quorum=for,abstain¶ms=fractional"; + } + + /// @inheritdoc IGovernor + function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) { + return usedVotes(proposalId, account) > 0; + } + + /** + * @dev Get the number of votes already cast by `account` for a proposal with `proposalId`. Useful for + * integrations that allow delegates to cast rolling, partial votes. + */ + function usedVotes(uint256 proposalId, address account) public view virtual returns (uint256) { + return _proposalVotes[proposalId].usedVotes[account]; + } + + /** + * @dev Get current distribution of votes for a given proposal. + */ + function proposalVotes( + uint256 proposalId + ) public view virtual returns (uint256 againstVotes, uint256 forVotes, uint256 abstainVotes) { + ProposalVote storage proposalVote = _proposalVotes[proposalId]; + return (proposalVote.againstVotes, proposalVote.forVotes, proposalVote.abstainVotes); + } + + /// @inheritdoc Governor + function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) { + ProposalVote storage proposalVote = _proposalVotes[proposalId]; + return quorum(proposalSnapshot(proposalId)) <= proposalVote.forVotes + proposalVote.abstainVotes; + } + + /** + * @dev See {Governor-_voteSucceeded}. In this module, forVotes must be > againstVotes. + */ + function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) { + ProposalVote storage proposalVote = _proposalVotes[proposalId]; + return proposalVote.forVotes > proposalVote.againstVotes; + } + + /** + * @dev See {Governor-_countVote}. Function that records the delegate's votes. + * + * Executing this function consumes (part of) the delegate's weight on the proposal. This weight can be + * distributed amongst the 3 options (Against, For, Abstain) by specifying a fractional `support`. + * + * This counting module supports two vote casting modes: nominal and fractional. + * + * - Nominal: A nominal vote is cast by setting `support` to one of the 3 bravo options (Against, For, Abstain). + * - Fractional: A fractional vote is cast by setting `support` to `type(uint8).max` (255). + * + * Casting a nominal vote requires `params` to be empty and consumes the delegate's full remaining weight on the + * proposal for the specified `support` option. This is similar to the {GovernorCountingSimple} module and follows + * the `VoteType` enum from Governor Bravo. As a consequence, no vote weight remains unspent so no further voting + * is possible (for this `proposalId` and this `account`). + * + * Casting a fractional vote consumes a fraction of the delegate's remaining weight on the proposal according to the + * weights the delegate assigns to each support option (Against, For, Abstain respectively). The sum total of the + * three decoded vote weights _must_ be less than or equal to the delegate's remaining weight on the proposal (i.e. + * their checkpointed total weight minus votes already cast on the proposal). This format can be produced using: + * + * `abi.encodePacked(uint128(againstVotes), uint128(forVotes), uint128(abstainVotes))` + * + * NOTE: Consider that fractional voting restricts the number of casted votes (in each category) to 128 bits. + * Depending on how many decimals the underlying token has, a single voter may require to split their vote into + * multiple vote operations. For precision higher than ~30 decimals, large token holders may require a + * potentially large number of calls to cast all their votes. The voter has the possibility to cast all the + * remaining votes in a single operation using the traditional "bravo" vote. + */ + // slither-disable-next-line cyclomatic-complexity + function _countVote( + uint256 proposalId, + address account, + uint8 support, + uint256 totalWeight, + bytes memory params + ) internal virtual override returns (uint256) { + // Compute number of remaining votes. Returns 0 on overflow. + (, uint256 remainingWeight) = totalWeight.trySub(usedVotes(proposalId, account)); + if (remainingWeight == 0) { + revert GovernorAlreadyCastVote(account); + } + + uint256 againstVotes = 0; + uint256 forVotes = 0; + uint256 abstainVotes = 0; + uint256 usedWeight = 0; + + // For clarity of event indexing, fractional voting must be clearly advertised in the "support" field. + // + // Supported `support` value must be: + // - "Full" voting: `support = 0` (Against), `1` (For) or `2` (Abstain), with empty params. + // - "Fractional" voting: `support = 255`, with 48 bytes params. + if (support == uint8(GovernorCountingSimple.VoteType.Against)) { + if (params.length != 0) revert GovernorInvalidVoteParams(); + usedWeight = againstVotes = remainingWeight; + } else if (support == uint8(GovernorCountingSimple.VoteType.For)) { + if (params.length != 0) revert GovernorInvalidVoteParams(); + usedWeight = forVotes = remainingWeight; + } else if (support == uint8(GovernorCountingSimple.VoteType.Abstain)) { + if (params.length != 0) revert GovernorInvalidVoteParams(); + usedWeight = abstainVotes = remainingWeight; + } else if (support == VOTE_TYPE_FRACTIONAL) { + // The `params` argument is expected to be three packed `uint128`: + // `abi.encodePacked(uint128(againstVotes), uint128(forVotes), uint128(abstainVotes))` + if (params.length != 0x30) revert GovernorInvalidVoteParams(); + + assembly ("memory-safe") { + againstVotes := shr(128, mload(add(params, 0x20))) + forVotes := shr(128, mload(add(params, 0x30))) + abstainVotes := shr(128, mload(add(params, 0x40))) + usedWeight := add(add(againstVotes, forVotes), abstainVotes) // inputs are uint128: cannot overflow + } + + // check parsed arguments are valid + if (usedWeight > remainingWeight) { + revert GovernorExceedRemainingWeight(account, usedWeight, remainingWeight); + } + } else { + revert GovernorInvalidVoteType(); + } + + // update votes tracking + ProposalVote storage details = _proposalVotes[proposalId]; + if (againstVotes > 0) details.againstVotes += againstVotes; + if (forVotes > 0) details.forVotes += forVotes; + if (abstainVotes > 0) details.abstainVotes += abstainVotes; + details.usedVotes[account] += usedWeight; + + return usedWeight; + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/governance/extensions/GovernorCountingOverridable.sol b/dependencies/@openzeppelin-contracts-5.4.0/governance/extensions/GovernorCountingOverridable.sol new file mode 100644 index 00000000..45a72ea7 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/governance/extensions/GovernorCountingOverridable.sol @@ -0,0 +1,222 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (governance/extensions/GovernorCountingOverridable.sol) + +pragma solidity ^0.8.24; + +import {SignatureChecker} from "../../utils/cryptography/SignatureChecker.sol"; +import {SafeCast} from "../../utils/math/SafeCast.sol"; +import {VotesExtended} from "../utils/VotesExtended.sol"; +import {GovernorVotes} from "./GovernorVotes.sol"; +import {IGovernor, Governor} from "../Governor.sol"; + +/** + * @dev Extension of {Governor} which enables delegators to override the vote of their delegates. This module requires a + * token that inherits {VotesExtended}. + */ +abstract contract GovernorCountingOverridable is GovernorVotes { + bytes32 public constant OVERRIDE_BALLOT_TYPEHASH = + keccak256("OverrideBallot(uint256 proposalId,uint8 support,address voter,uint256 nonce,string reason)"); + + /** + * @dev Supported vote types. Matches Governor Bravo ordering. + */ + enum VoteType { + Against, + For, + Abstain + } + + struct VoteReceipt { + uint8 casted; // 0 if vote was not casted. Otherwise: support + 1 + bool hasOverridden; + uint208 overriddenWeight; + } + + struct ProposalVote { + uint256[3] votes; + mapping(address voter => VoteReceipt) voteReceipt; + } + + /// @dev The votes casted by `delegate` were reduced by `weight` after an override vote was casted by the original token holder + event VoteReduced(address indexed delegate, uint256 proposalId, uint8 support, uint256 weight); + + /// @dev A delegated vote on `proposalId` was overridden by `weight` + event OverrideVoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason); + + error GovernorAlreadyOverriddenVote(address account); + + mapping(uint256 proposalId => ProposalVote) private _proposalVotes; + + /// @inheritdoc IGovernor + // solhint-disable-next-line func-name-mixedcase + function COUNTING_MODE() public pure virtual override returns (string memory) { + return "support=bravo,override&quorum=for,abstain&overridable=true"; + } + + /** + * @dev See {IGovernor-hasVoted}. + * + * NOTE: Calling {castVote} (or similar) casts a vote using the voting power that is delegated to the voter. + * Conversely, calling {castOverrideVote} (or similar) uses the voting power of the account itself, from its asset + * balances. Casting an "override vote" does not count as voting and won't be reflected by this getter. Consider + * using {hasVotedOverride} to check if an account has casted an "override vote" for a given proposal id. + */ + function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) { + return _proposalVotes[proposalId].voteReceipt[account].casted != 0; + } + + /** + * @dev Check if an `account` has overridden their delegate for a proposal. + */ + function hasVotedOverride(uint256 proposalId, address account) public view virtual returns (bool) { + return _proposalVotes[proposalId].voteReceipt[account].hasOverridden; + } + + /** + * @dev Accessor to the internal vote counts. + */ + function proposalVotes( + uint256 proposalId + ) public view virtual returns (uint256 againstVotes, uint256 forVotes, uint256 abstainVotes) { + uint256[3] storage votes = _proposalVotes[proposalId].votes; + return (votes[uint8(VoteType.Against)], votes[uint8(VoteType.For)], votes[uint8(VoteType.Abstain)]); + } + + /// @inheritdoc Governor + function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) { + uint256[3] storage votes = _proposalVotes[proposalId].votes; + return quorum(proposalSnapshot(proposalId)) <= votes[uint8(VoteType.For)] + votes[uint8(VoteType.Abstain)]; + } + + /** + * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes. + */ + function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) { + uint256[3] storage votes = _proposalVotes[proposalId].votes; + return votes[uint8(VoteType.For)] > votes[uint8(VoteType.Against)]; + } + + /** + * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo). + * + * NOTE: called by {Governor-_castVote} which emits the {IGovernor-VoteCast} (or {IGovernor-VoteCastWithParams}) + * event. + */ + function _countVote( + uint256 proposalId, + address account, + uint8 support, + uint256 totalWeight, + bytes memory /*params*/ + ) internal virtual override returns (uint256) { + ProposalVote storage proposalVote = _proposalVotes[proposalId]; + + if (support > uint8(VoteType.Abstain)) { + revert GovernorInvalidVoteType(); + } + + if (proposalVote.voteReceipt[account].casted != 0) { + revert GovernorAlreadyCastVote(account); + } + + totalWeight -= proposalVote.voteReceipt[account].overriddenWeight; + proposalVote.votes[support] += totalWeight; + proposalVote.voteReceipt[account].casted = support + 1; + + return totalWeight; + } + + /** + * @dev Variant of {Governor-_countVote} that deals with vote overrides. + * + * NOTE: See {hasVoted} for more details about the difference between {castVote} and {castOverrideVote}. + */ + function _countOverride(uint256 proposalId, address account, uint8 support) internal virtual returns (uint256) { + ProposalVote storage proposalVote = _proposalVotes[proposalId]; + + if (support > uint8(VoteType.Abstain)) { + revert GovernorInvalidVoteType(); + } + + if (proposalVote.voteReceipt[account].hasOverridden) { + revert GovernorAlreadyOverriddenVote(account); + } + + uint256 snapshot = proposalSnapshot(proposalId); + uint256 overriddenWeight = VotesExtended(address(token())).getPastBalanceOf(account, snapshot); + address delegate = VotesExtended(address(token())).getPastDelegate(account, snapshot); + uint8 delegateCasted = proposalVote.voteReceipt[delegate].casted; + + proposalVote.voteReceipt[account].hasOverridden = true; + proposalVote.votes[support] += overriddenWeight; + if (delegateCasted == 0) { + proposalVote.voteReceipt[delegate].overriddenWeight += SafeCast.toUint208(overriddenWeight); + } else { + uint8 delegateSupport = delegateCasted - 1; + proposalVote.votes[delegateSupport] -= overriddenWeight; + emit VoteReduced(delegate, proposalId, delegateSupport, overriddenWeight); + } + + return overriddenWeight; + } + + /// @dev Variant of {Governor-_castVote} that deals with vote overrides. Returns the overridden weight. + function _castOverride( + uint256 proposalId, + address account, + uint8 support, + string calldata reason + ) internal virtual returns (uint256) { + _validateStateBitmap(proposalId, _encodeStateBitmap(ProposalState.Active)); + + uint256 overriddenWeight = _countOverride(proposalId, account, support); + + emit OverrideVoteCast(account, proposalId, support, overriddenWeight, reason); + + _tallyUpdated(proposalId); + + return overriddenWeight; + } + + /// @dev Public function for casting an override vote. Returns the overridden weight. + function castOverrideVote( + uint256 proposalId, + uint8 support, + string calldata reason + ) public virtual returns (uint256) { + address voter = _msgSender(); + return _castOverride(proposalId, voter, support, reason); + } + + /// @dev Public function for casting an override vote using a voter's signature. Returns the overridden weight. + function castOverrideVoteBySig( + uint256 proposalId, + uint8 support, + address voter, + string calldata reason, + bytes calldata signature + ) public virtual returns (uint256) { + bool valid = SignatureChecker.isValidSignatureNow( + voter, + _hashTypedDataV4( + keccak256( + abi.encode( + OVERRIDE_BALLOT_TYPEHASH, + proposalId, + support, + voter, + _useNonce(voter), + keccak256(bytes(reason)) + ) + ) + ), + signature + ); + + if (!valid) { + revert GovernorInvalidSignature(voter); + } + + return _castOverride(proposalId, voter, support, reason); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/governance/extensions/GovernorCountingSimple.sol b/dependencies/@openzeppelin-contracts-5.4.0/governance/extensions/GovernorCountingSimple.sol new file mode 100644 index 00000000..3f24a657 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/governance/extensions/GovernorCountingSimple.sol @@ -0,0 +1,96 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (governance/extensions/GovernorCountingSimple.sol) + +pragma solidity ^0.8.24; + +import {IGovernor, Governor} from "../Governor.sol"; + +/** + * @dev Extension of {Governor} for simple, 3 options, vote counting. + */ +abstract contract GovernorCountingSimple is Governor { + /** + * @dev Supported vote types. Matches Governor Bravo ordering. + */ + enum VoteType { + Against, + For, + Abstain + } + + struct ProposalVote { + uint256 againstVotes; + uint256 forVotes; + uint256 abstainVotes; + mapping(address voter => bool) hasVoted; + } + + mapping(uint256 proposalId => ProposalVote) private _proposalVotes; + + /// @inheritdoc IGovernor + // solhint-disable-next-line func-name-mixedcase + function COUNTING_MODE() public pure virtual override returns (string memory) { + return "support=bravo&quorum=for,abstain"; + } + + /// @inheritdoc IGovernor + function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) { + return _proposalVotes[proposalId].hasVoted[account]; + } + + /** + * @dev Accessor to the internal vote counts. + */ + function proposalVotes( + uint256 proposalId + ) public view virtual returns (uint256 againstVotes, uint256 forVotes, uint256 abstainVotes) { + ProposalVote storage proposalVote = _proposalVotes[proposalId]; + return (proposalVote.againstVotes, proposalVote.forVotes, proposalVote.abstainVotes); + } + + /// @inheritdoc Governor + function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) { + ProposalVote storage proposalVote = _proposalVotes[proposalId]; + + return quorum(proposalSnapshot(proposalId)) <= proposalVote.forVotes + proposalVote.abstainVotes; + } + + /** + * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes. + */ + function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) { + ProposalVote storage proposalVote = _proposalVotes[proposalId]; + + return proposalVote.forVotes > proposalVote.againstVotes; + } + + /** + * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo). + */ + function _countVote( + uint256 proposalId, + address account, + uint8 support, + uint256 totalWeight, + bytes memory // params + ) internal virtual override returns (uint256) { + ProposalVote storage proposalVote = _proposalVotes[proposalId]; + + if (proposalVote.hasVoted[account]) { + revert GovernorAlreadyCastVote(account); + } + proposalVote.hasVoted[account] = true; + + if (support == uint8(VoteType.Against)) { + proposalVote.againstVotes += totalWeight; + } else if (support == uint8(VoteType.For)) { + proposalVote.forVotes += totalWeight; + } else if (support == uint8(VoteType.Abstain)) { + proposalVote.abstainVotes += totalWeight; + } else { + revert GovernorInvalidVoteType(); + } + + return totalWeight; + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/governance/extensions/GovernorNoncesKeyed.sol b/dependencies/@openzeppelin-contracts-5.4.0/governance/extensions/GovernorNoncesKeyed.sol new file mode 100644 index 00000000..c506b7e3 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/governance/extensions/GovernorNoncesKeyed.sol @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (governance/extensions/GovernorNoncesKeyed.sol) + +pragma solidity ^0.8.24; + +import {Governor} from "../Governor.sol"; +import {Nonces} from "../../utils/Nonces.sol"; +import {NoncesKeyed} from "../../utils/NoncesKeyed.sol"; +import {SignatureChecker} from "../../utils/cryptography/SignatureChecker.sol"; + +/** + * @dev An extension of {Governor} that extends existing nonce management to use {NoncesKeyed}, where the key is the low-order 192 bits of the `proposalId`. + * This is useful for voting by signature while maintaining separate sequences of nonces for each proposal. + * + * NOTE: Traditional (un-keyed) nonces are still supported and can continue to be used as if this extension was not present. + */ +abstract contract GovernorNoncesKeyed is Governor, NoncesKeyed { + function _useCheckedNonce(address owner, uint256 nonce) internal virtual override(Nonces, NoncesKeyed) { + super._useCheckedNonce(owner, nonce); + } + + /** + * @dev Check the signature against keyed nonce and falls back to the traditional nonce. + * + * NOTE: This function won't call `super._validateVoteSig` if the keyed nonce is valid. + * Side effects may be skipped depending on the linearization of the function. + */ + function _validateVoteSig( + uint256 proposalId, + uint8 support, + address voter, + bytes memory signature + ) internal virtual override returns (bool) { + if ( + SignatureChecker.isValidSignatureNow( + voter, + _hashTypedDataV4( + keccak256( + abi.encode(BALLOT_TYPEHASH, proposalId, support, voter, nonces(voter, uint192(proposalId))) + ) + ), + signature + ) + ) { + _useNonce(voter, uint192(proposalId)); + return true; + } else { + return super._validateVoteSig(proposalId, support, voter, signature); + } + } + + /** + * @dev Check the signature against keyed nonce and falls back to the traditional nonce. + * + * NOTE: This function won't call `super._validateExtendedVoteSig` if the keyed nonce is valid. + * Side effects may be skipped depending on the linearization of the function. + */ + function _validateExtendedVoteSig( + uint256 proposalId, + uint8 support, + address voter, + string memory reason, + bytes memory params, + bytes memory signature + ) internal virtual override returns (bool) { + if ( + SignatureChecker.isValidSignatureNow( + voter, + _hashTypedDataV4( + keccak256( + abi.encode( + EXTENDED_BALLOT_TYPEHASH, + proposalId, + support, + voter, + nonces(voter, uint192(proposalId)), + keccak256(bytes(reason)), + keccak256(params) + ) + ) + ), + signature + ) + ) { + _useNonce(voter, uint192(proposalId)); + return true; + } else { + return super._validateExtendedVoteSig(proposalId, support, voter, reason, params, signature); + } + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/governance/extensions/GovernorPreventLateQuorum.sol b/dependencies/@openzeppelin-contracts-5.4.0/governance/extensions/GovernorPreventLateQuorum.sol new file mode 100644 index 00000000..581f96e5 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/governance/extensions/GovernorPreventLateQuorum.sol @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (governance/extensions/GovernorPreventLateQuorum.sol) + +pragma solidity ^0.8.24; + +import {Governor} from "../Governor.sol"; +import {Math} from "../../utils/math/Math.sol"; + +/** + * @dev A module that ensures there is a minimum voting period after quorum is reached. This prevents a large voter from + * swaying a vote and triggering quorum at the last minute, by ensuring there is always time for other voters to react + * and try to oppose the decision. + * + * If a vote causes quorum to be reached, the proposal's voting period may be extended so that it does not end before at + * least a specified time has passed (the "vote extension" parameter). This parameter can be set through a governance + * proposal. + */ +abstract contract GovernorPreventLateQuorum is Governor { + uint48 private _voteExtension; + + mapping(uint256 proposalId => uint48) private _extendedDeadlines; + + /// @dev Emitted when a proposal deadline is pushed back due to reaching quorum late in its voting period. + event ProposalExtended(uint256 indexed proposalId, uint64 extendedDeadline); + + /// @dev Emitted when the {lateQuorumVoteExtension} parameter is changed. + event LateQuorumVoteExtensionSet(uint64 oldVoteExtension, uint64 newVoteExtension); + + /** + * @dev Initializes the vote extension parameter: the time in either number of blocks or seconds (depending on the + * governor clock mode) that is required to pass since the moment a proposal reaches quorum until its voting period + * ends. If necessary the voting period will be extended beyond the one set during proposal creation. + */ + constructor(uint48 initialVoteExtension) { + _setLateQuorumVoteExtension(initialVoteExtension); + } + + /** + * @dev Returns the proposal deadline, which may have been extended beyond that set at proposal creation, if the + * proposal reached quorum late in the voting period. See {Governor-proposalDeadline}. + */ + function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) { + return Math.max(super.proposalDeadline(proposalId), _extendedDeadlines[proposalId]); + } + + /** + * @dev Vote tally updated and detects if it caused quorum to be reached, potentially extending the voting period. + * + * May emit a {ProposalExtended} event. + */ + function _tallyUpdated(uint256 proposalId) internal virtual override { + super._tallyUpdated(proposalId); + if (_extendedDeadlines[proposalId] == 0 && _quorumReached(proposalId)) { + uint48 extendedDeadline = clock() + lateQuorumVoteExtension(); + + if (extendedDeadline > proposalDeadline(proposalId)) { + emit ProposalExtended(proposalId, extendedDeadline); + } + + _extendedDeadlines[proposalId] = extendedDeadline; + } + } + + /** + * @dev Returns the current value of the vote extension parameter: the number of blocks that are required to pass + * from the time a proposal reaches quorum until its voting period ends. + */ + function lateQuorumVoteExtension() public view virtual returns (uint48) { + return _voteExtension; + } + + /** + * @dev Changes the {lateQuorumVoteExtension}. This operation can only be performed by the governance executor, + * generally through a governance proposal. + * + * Emits a {LateQuorumVoteExtensionSet} event. + */ + function setLateQuorumVoteExtension(uint48 newVoteExtension) public virtual onlyGovernance { + _setLateQuorumVoteExtension(newVoteExtension); + } + + /** + * @dev Changes the {lateQuorumVoteExtension}. This is an internal function that can be exposed in a public function + * like {setLateQuorumVoteExtension} if another access control mechanism is needed. + * + * Emits a {LateQuorumVoteExtensionSet} event. + */ + function _setLateQuorumVoteExtension(uint48 newVoteExtension) internal virtual { + emit LateQuorumVoteExtensionSet(_voteExtension, newVoteExtension); + _voteExtension = newVoteExtension; + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/governance/extensions/GovernorProposalGuardian.sol b/dependencies/@openzeppelin-contracts-5.4.0/governance/extensions/GovernorProposalGuardian.sol new file mode 100644 index 00000000..5ff0c180 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/governance/extensions/GovernorProposalGuardian.sol @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (governance/extensions/GovernorProposalGuardian.sol) +pragma solidity ^0.8.24; + +import {Governor} from "../Governor.sol"; + +/** + * @dev Extension of {Governor} which adds a proposal guardian that can cancel proposals at any stage in the proposal's lifecycle. + * + * NOTE: if the proposal guardian is not configured, then proposers take this role for their proposals. + */ +abstract contract GovernorProposalGuardian is Governor { + address private _proposalGuardian; + + event ProposalGuardianSet(address oldProposalGuardian, address newProposalGuardian); + + /** + * @dev Getter that returns the address of the proposal guardian. + */ + function proposalGuardian() public view virtual returns (address) { + return _proposalGuardian; + } + + /** + * @dev Update the proposal guardian's address. This operation can only be performed through a governance proposal. + * + * Emits a {ProposalGuardianSet} event. + */ + function setProposalGuardian(address newProposalGuardian) public virtual onlyGovernance { + _setProposalGuardian(newProposalGuardian); + } + + /** + * @dev Internal setter for the proposal guardian. + * + * Emits a {ProposalGuardianSet} event. + */ + function _setProposalGuardian(address newProposalGuardian) internal virtual { + emit ProposalGuardianSet(_proposalGuardian, newProposalGuardian); + _proposalGuardian = newProposalGuardian; + } + + /** + * @dev Override {Governor-_validateCancel} to implement the extended cancellation logic. + * + * * The {proposalGuardian} can cancel any proposal at any point. + * * If no proposal guardian is set, the {IGovernor-proposalProposer} can cancel their proposals at any point. + * * In any case, permissions defined in {Governor-_validateCancel} (or another override) remains valid. + */ + function _validateCancel(uint256 proposalId, address caller) internal view virtual override returns (bool) { + address guardian = proposalGuardian(); + + return + guardian == caller || + (guardian == address(0) && caller == proposalProposer(proposalId)) || + super._validateCancel(proposalId, caller); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/governance/extensions/GovernorSequentialProposalId.sol b/dependencies/@openzeppelin-contracts-5.4.0/governance/extensions/GovernorSequentialProposalId.sol new file mode 100644 index 00000000..d6869bbd --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/governance/extensions/GovernorSequentialProposalId.sol @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (governance/extensions/GovernorSequentialProposalId.sol) + +pragma solidity ^0.8.24; + +import {IGovernor, Governor} from "../Governor.sol"; + +/** + * @dev Extension of {Governor} that changes the numbering of proposal ids from the default hash-based approach to + * sequential ids. + */ +abstract contract GovernorSequentialProposalId is Governor { + uint256 private _latestProposalId; + mapping(uint256 proposalHash => uint256 proposalId) private _proposalIds; + + /** + * @dev The {latestProposalId} may only be initialized if it hasn't been set yet + * (through initialization or the creation of a proposal). + */ + error GovernorAlreadyInitializedLatestProposalId(); + + /// @inheritdoc IGovernor + function getProposalId( + address[] memory targets, + uint256[] memory values, + bytes[] memory calldatas, + bytes32 descriptionHash + ) public view virtual override returns (uint256) { + uint256 proposalHash = hashProposal(targets, values, calldatas, descriptionHash); + uint256 storedProposalId = _proposalIds[proposalHash]; + if (storedProposalId == 0) { + revert GovernorNonexistentProposal(0); + } + return storedProposalId; + } + + /** + * @dev Returns the latest proposal id. A return value of 0 means no proposals have been created yet. + */ + function latestProposalId() public view virtual returns (uint256) { + return _latestProposalId; + } + + /** + * @dev See {IGovernor-_propose}. + * Hook into the proposing mechanism to increment proposal count. + */ + function _propose( + address[] memory targets, + uint256[] memory values, + bytes[] memory calldatas, + string memory description, + address proposer + ) internal virtual override returns (uint256) { + uint256 proposalHash = hashProposal(targets, values, calldatas, keccak256(bytes(description))); + uint256 storedProposalId = _proposalIds[proposalHash]; + if (storedProposalId == 0) { + _proposalIds[proposalHash] = ++_latestProposalId; + } + return super._propose(targets, values, calldatas, description, proposer); + } + + /** + * @dev Internal function to set the {latestProposalId}. This function is helpful when transitioning + * from another governance system. The next proposal id will be `newLatestProposalId` + 1. + * + * May only call this function if the current value of {latestProposalId} is 0. + */ + function _initializeLatestProposalId(uint256 newLatestProposalId) internal virtual { + if (_latestProposalId != 0) { + revert GovernorAlreadyInitializedLatestProposalId(); + } + _latestProposalId = newLatestProposalId; + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/governance/extensions/GovernorSettings.sol b/dependencies/@openzeppelin-contracts-5.4.0/governance/extensions/GovernorSettings.sol new file mode 100644 index 00000000..5f3cef77 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/governance/extensions/GovernorSettings.sol @@ -0,0 +1,106 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (governance/extensions/GovernorSettings.sol) + +pragma solidity ^0.8.24; + +import {IGovernor, Governor} from "../Governor.sol"; + +/** + * @dev Extension of {Governor} for settings updatable through governance. + */ +abstract contract GovernorSettings is Governor { + // amount of token + uint256 private _proposalThreshold; + // timepoint: limited to uint48 in core (same as clock() type) + uint48 private _votingDelay; + // duration: limited to uint32 in core + uint32 private _votingPeriod; + + event VotingDelaySet(uint256 oldVotingDelay, uint256 newVotingDelay); + event VotingPeriodSet(uint256 oldVotingPeriod, uint256 newVotingPeriod); + event ProposalThresholdSet(uint256 oldProposalThreshold, uint256 newProposalThreshold); + + /** + * @dev Initialize the governance parameters. + */ + constructor(uint48 initialVotingDelay, uint32 initialVotingPeriod, uint256 initialProposalThreshold) { + _setVotingDelay(initialVotingDelay); + _setVotingPeriod(initialVotingPeriod); + _setProposalThreshold(initialProposalThreshold); + } + + /// @inheritdoc IGovernor + function votingDelay() public view virtual override returns (uint256) { + return _votingDelay; + } + + /// @inheritdoc IGovernor + function votingPeriod() public view virtual override returns (uint256) { + return _votingPeriod; + } + + /// @inheritdoc Governor + function proposalThreshold() public view virtual override returns (uint256) { + return _proposalThreshold; + } + + /** + * @dev Update the voting delay. This operation can only be performed through a governance proposal. + * + * Emits a {VotingDelaySet} event. + */ + function setVotingDelay(uint48 newVotingDelay) public virtual onlyGovernance { + _setVotingDelay(newVotingDelay); + } + + /** + * @dev Update the voting period. This operation can only be performed through a governance proposal. + * + * Emits a {VotingPeriodSet} event. + */ + function setVotingPeriod(uint32 newVotingPeriod) public virtual onlyGovernance { + _setVotingPeriod(newVotingPeriod); + } + + /** + * @dev Update the proposal threshold. This operation can only be performed through a governance proposal. + * + * Emits a {ProposalThresholdSet} event. + */ + function setProposalThreshold(uint256 newProposalThreshold) public virtual onlyGovernance { + _setProposalThreshold(newProposalThreshold); + } + + /** + * @dev Internal setter for the voting delay. + * + * Emits a {VotingDelaySet} event. + */ + function _setVotingDelay(uint48 newVotingDelay) internal virtual { + emit VotingDelaySet(_votingDelay, newVotingDelay); + _votingDelay = newVotingDelay; + } + + /** + * @dev Internal setter for the voting period. + * + * Emits a {VotingPeriodSet} event. + */ + function _setVotingPeriod(uint32 newVotingPeriod) internal virtual { + if (newVotingPeriod == 0) { + revert GovernorInvalidVotingPeriod(0); + } + emit VotingPeriodSet(_votingPeriod, newVotingPeriod); + _votingPeriod = newVotingPeriod; + } + + /** + * @dev Internal setter for the proposal threshold. + * + * Emits a {ProposalThresholdSet} event. + */ + function _setProposalThreshold(uint256 newProposalThreshold) internal virtual { + emit ProposalThresholdSet(_proposalThreshold, newProposalThreshold); + _proposalThreshold = newProposalThreshold; + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/governance/extensions/GovernorStorage.sol b/dependencies/@openzeppelin-contracts-5.4.0/governance/extensions/GovernorStorage.sol new file mode 100644 index 00000000..1c006786 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/governance/extensions/GovernorStorage.sol @@ -0,0 +1,125 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (governance/extensions/GovernorStorage.sol) + +pragma solidity ^0.8.24; + +import {Governor} from "../Governor.sol"; + +/** + * @dev Extension of {Governor} that implements storage of proposal details. This modules also provides primitives for + * the enumerability of proposals. + * + * Use cases for this module include: + * - UIs that explore the proposal state without relying on event indexing. + * - Using only the proposalId as an argument in the {Governor-queue} and {Governor-execute} functions for L2 chains + * where storage is cheap compared to calldata. + */ +abstract contract GovernorStorage is Governor { + struct ProposalDetails { + address[] targets; + uint256[] values; + bytes[] calldatas; + bytes32 descriptionHash; + } + + uint256[] private _proposalIds; + mapping(uint256 proposalId => ProposalDetails) private _proposalDetails; + + /** + * @dev Hook into the proposing mechanism + */ + function _propose( + address[] memory targets, + uint256[] memory values, + bytes[] memory calldatas, + string memory description, + address proposer + ) internal virtual override returns (uint256) { + uint256 proposalId = super._propose(targets, values, calldatas, description, proposer); + + // store + _proposalIds.push(proposalId); + _proposalDetails[proposalId] = ProposalDetails({ + targets: targets, + values: values, + calldatas: calldatas, + descriptionHash: keccak256(bytes(description)) + }); + + return proposalId; + } + + /** + * @dev Version of {IGovernor-queue} with only `proposalId` as an argument. + */ + function queue(uint256 proposalId) public virtual { + // here, using storage is more efficient than memory + ProposalDetails storage details = _proposalDetails[proposalId]; + queue(details.targets, details.values, details.calldatas, details.descriptionHash); + } + + /** + * @dev Version of {IGovernor-execute} with only `proposalId` as an argument. + */ + function execute(uint256 proposalId) public payable virtual { + // here, using storage is more efficient than memory + ProposalDetails storage details = _proposalDetails[proposalId]; + execute(details.targets, details.values, details.calldatas, details.descriptionHash); + } + + /** + * @dev ProposalId version of {IGovernor-cancel}. + */ + function cancel(uint256 proposalId) public virtual { + // here, using storage is more efficient than memory + ProposalDetails storage details = _proposalDetails[proposalId]; + cancel(details.targets, details.values, details.calldatas, details.descriptionHash); + } + + /** + * @dev Returns the number of stored proposals. + */ + function proposalCount() public view virtual returns (uint256) { + return _proposalIds.length; + } + + /** + * @dev Returns the details of a proposalId. Reverts if `proposalId` is not a known proposal. + */ + function proposalDetails( + uint256 proposalId + ) + public + view + virtual + returns (address[] memory targets, uint256[] memory values, bytes[] memory calldatas, bytes32 descriptionHash) + { + // here, using memory is more efficient than storage + ProposalDetails memory details = _proposalDetails[proposalId]; + if (details.descriptionHash == 0) { + revert GovernorNonexistentProposal(proposalId); + } + return (details.targets, details.values, details.calldatas, details.descriptionHash); + } + + /** + * @dev Returns the details (including the proposalId) of a proposal given its sequential index. + */ + function proposalDetailsAt( + uint256 index + ) + public + view + virtual + returns ( + uint256 proposalId, + address[] memory targets, + uint256[] memory values, + bytes[] memory calldatas, + bytes32 descriptionHash + ) + { + proposalId = _proposalIds[index]; + (targets, values, calldatas, descriptionHash) = proposalDetails(proposalId); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/governance/extensions/GovernorSuperQuorum.sol b/dependencies/@openzeppelin-contracts-5.4.0/governance/extensions/GovernorSuperQuorum.sol new file mode 100644 index 00000000..04602fdb --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/governance/extensions/GovernorSuperQuorum.sol @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (governance/extensions/GovernorSuperQuorum.sol) +pragma solidity ^0.8.24; + +import {Governor} from "../Governor.sol"; + +/** + * @dev Extension of {Governor} with a super quorum. Proposals that meet the super quorum (and have a majority of for + * votes) advance to the `Succeeded` state before the proposal deadline. Counting modules that want to use this + * extension must implement {proposalVotes}. + */ +abstract contract GovernorSuperQuorum is Governor { + /** + * @dev Minimum number of cast votes required for a proposal to reach super quorum. Only FOR votes are counted + * towards the super quorum. Once the super quorum is reached, an active proposal can proceed to the next state + * without waiting for the proposal deadline. + * + * NOTE: The `timepoint` parameter corresponds to the snapshot used for counting the vote. This enables scaling of the + * quorum depending on values such as the `totalSupply` of a token at this timepoint (see {ERC20Votes}). + * + * NOTE: Make sure the value specified for the super quorum is greater than {quorum}, otherwise, it may be + * possible to pass a proposal with less votes than the default quorum. + */ + function superQuorum(uint256 timepoint) public view virtual returns (uint256); + + /** + * @dev Accessor to the internal vote counts. This must be implemented by the counting module. Counting modules + * that don't implement this function are incompatible with this module + */ + function proposalVotes( + uint256 proposalId + ) public view virtual returns (uint256 againstVotes, uint256 forVotes, uint256 abstainVotes); + + /** + * @dev Overridden version of the {Governor-state} function that checks if the proposal has reached the super + * quorum. + * + * NOTE: If the proposal reaches super quorum but {_voteSucceeded} returns false, eg, assuming the super quorum + * has been set low enough that both FOR and AGAINST votes have exceeded it and AGAINST votes exceed FOR votes, + * the proposal continues to be active until {_voteSucceeded} returns true or the proposal deadline is reached. + * This means that with a low super quorum it is also possible that a vote can succeed prematurely before enough + * AGAINST voters have a chance to vote. Hence, it is recommended to set a high enough super quorum to avoid these + * types of scenarios. + */ + function state(uint256 proposalId) public view virtual override returns (ProposalState) { + ProposalState currentState = super.state(proposalId); + if (currentState != ProposalState.Active) return currentState; + + (, uint256 forVotes, ) = proposalVotes(proposalId); + if (forVotes < superQuorum(proposalSnapshot(proposalId)) || !_voteSucceeded(proposalId)) { + return ProposalState.Active; + } else if (proposalEta(proposalId) == 0) { + return ProposalState.Succeeded; + } else { + return ProposalState.Queued; + } + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/governance/extensions/GovernorTimelockAccess.sol b/dependencies/@openzeppelin-contracts-5.4.0/governance/extensions/GovernorTimelockAccess.sol new file mode 100644 index 00000000..14823d90 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/governance/extensions/GovernorTimelockAccess.sol @@ -0,0 +1,346 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (governance/extensions/GovernorTimelockAccess.sol) + +pragma solidity ^0.8.24; + +import {IGovernor, Governor} from "../Governor.sol"; +import {AuthorityUtils} from "../../access/manager/AuthorityUtils.sol"; +import {IAccessManager} from "../../access/manager/IAccessManager.sol"; +import {Address} from "../../utils/Address.sol"; +import {Math} from "../../utils/math/Math.sol"; +import {SafeCast} from "../../utils/math/SafeCast.sol"; +import {Time} from "../../utils/types/Time.sol"; + +/** + * @dev This module connects a {Governor} instance to an {AccessManager} instance, allowing the governor to make calls + * that are delay-restricted by the manager using the normal {queue} workflow. An optional base delay is applied to + * operations that are not delayed externally by the manager. Execution of a proposal will be delayed as much as + * necessary to meet the required delays of all of its operations. + * + * This extension allows the governor to hold and use its own assets and permissions, unlike {GovernorTimelockControl} + * and {GovernorTimelockCompound}, where the timelock is a separate contract that must be the one to hold assets and + * permissions. Operations that are delay-restricted by the manager, however, will be executed through the + * {AccessManager-execute} function. + * + * ==== Security Considerations + * + * Some operations may be cancelable in the `AccessManager` by the admin or a set of guardians, depending on the + * restricted function being invoked. Since proposals are atomic, the cancellation by a guardian of a single operation + * in a proposal will cause all of the proposal to become unable to execute. Consider proposing cancellable operations + * separately. + * + * By default, function calls will be routed through the associated `AccessManager` whenever it claims the target + * function to be restricted by it. However, admins may configure the manager to make that claim for functions that a + * governor would want to call directly (e.g., token transfers) in an attempt to deny it access to those functions. To + * mitigate this attack vector, the governor is able to ignore the restrictions claimed by the `AccessManager` using + * {setAccessManagerIgnored}. While permanent denial of service is mitigated, temporary DoS may still be technically + * possible. All of the governor's own functions (e.g., {setBaseDelaySeconds}) ignore the `AccessManager` by default. + * + * NOTE: `AccessManager` does not support scheduling more than one operation with the same target and calldata at + * the same time. See {AccessManager-schedule} for a workaround. + */ +abstract contract GovernorTimelockAccess is Governor { + // An execution plan is produced at the moment a proposal is created, in order to fix at that point the exact + // execution semantics of the proposal, namely whether a call will go through {AccessManager-execute}. + struct ExecutionPlan { + uint16 length; + uint32 delay; + // We use mappings instead of arrays because it allows us to pack values in storage more tightly without + // storing the length redundantly. + // We pack 8 operations' data in each bucket. Each uint32 value is set to 1 upon proposal creation if it has + // to be scheduled and executed through the manager. Upon queuing, the value is set to nonce + 2, where the + // nonce is received from the manager when scheduling the operation. + mapping(uint256 operationBucket => uint32[8]) managerData; + } + + // The meaning of the "toggle" set to true depends on the target contract. + // If target == address(this), the manager is ignored by default, and a true toggle means it won't be ignored. + // For all other target contracts, the manager is used by default, and a true toggle means it will be ignored. + mapping(address target => mapping(bytes4 selector => bool)) private _ignoreToggle; + + mapping(uint256 proposalId => ExecutionPlan) private _executionPlan; + + uint32 private _baseDelay; + + IAccessManager private immutable _manager; + + error GovernorUnmetDelay(uint256 proposalId, uint256 neededTimestamp); + error GovernorMismatchedNonce(uint256 proposalId, uint256 expectedNonce, uint256 actualNonce); + error GovernorLockedIgnore(); + + event BaseDelaySet(uint32 oldBaseDelaySeconds, uint32 newBaseDelaySeconds); + event AccessManagerIgnoredSet(address target, bytes4 selector, bool ignored); + + /** + * @dev Initialize the governor with an {AccessManager} and initial base delay. + */ + constructor(address manager, uint32 initialBaseDelay) { + _manager = IAccessManager(manager); + _setBaseDelaySeconds(initialBaseDelay); + } + + /** + * @dev Returns the {AccessManager} instance associated to this governor. + */ + function accessManager() public view virtual returns (IAccessManager) { + return _manager; + } + + /** + * @dev Base delay that will be applied to all function calls. Some may be further delayed by their associated + * `AccessManager` authority; in this case the final delay will be the maximum of the base delay and the one + * demanded by the authority. + * + * NOTE: Execution delays are processed by the `AccessManager` contracts, and according to that contract are + * expressed in seconds. Therefore, the base delay is also in seconds, regardless of the governor's clock mode. + */ + function baseDelaySeconds() public view virtual returns (uint32) { + return _baseDelay; + } + + /** + * @dev Change the value of {baseDelaySeconds}. This operation can only be invoked through a governance proposal. + */ + function setBaseDelaySeconds(uint32 newBaseDelay) public virtual onlyGovernance { + _setBaseDelaySeconds(newBaseDelay); + } + + /** + * @dev Change the value of {baseDelaySeconds}. Internal function without access control. + */ + function _setBaseDelaySeconds(uint32 newBaseDelay) internal virtual { + emit BaseDelaySet(_baseDelay, newBaseDelay); + _baseDelay = newBaseDelay; + } + + /** + * @dev Check if restrictions from the associated {AccessManager} are ignored for a target function. Returns true + * when the target function will be invoked directly regardless of `AccessManager` settings for the function. + * See {setAccessManagerIgnored} and Security Considerations above. + */ + function isAccessManagerIgnored(address target, bytes4 selector) public view virtual returns (bool) { + bool isGovernor = target == address(this); + return _ignoreToggle[target][selector] != isGovernor; // equivalent to: isGovernor ? !toggle : toggle + } + + /** + * @dev Configure whether restrictions from the associated {AccessManager} are ignored for a target function. + * See Security Considerations above. + */ + function setAccessManagerIgnored( + address target, + bytes4[] calldata selectors, + bool ignored + ) public virtual onlyGovernance { + for (uint256 i = 0; i < selectors.length; ++i) { + _setAccessManagerIgnored(target, selectors[i], ignored); + } + } + + /** + * @dev Internal version of {setAccessManagerIgnored} without access restriction. + */ + function _setAccessManagerIgnored(address target, bytes4 selector, bool ignored) internal virtual { + bool isGovernor = target == address(this); + if (isGovernor && selector == this.setAccessManagerIgnored.selector) { + revert GovernorLockedIgnore(); + } + _ignoreToggle[target][selector] = ignored != isGovernor; // equivalent to: isGovernor ? !ignored : ignored + emit AccessManagerIgnoredSet(target, selector, ignored); + } + + /** + * @dev Public accessor to check the execution plan, including the number of seconds that the proposal will be + * delayed since queuing, an array indicating which of the proposal actions will be executed indirectly through + * the associated {AccessManager}, and another indicating which will be scheduled in {queue}. Note that + * those that must be scheduled are cancellable by `AccessManager` guardians. + */ + function proposalExecutionPlan( + uint256 proposalId + ) public view returns (uint32 delay, bool[] memory indirect, bool[] memory withDelay) { + ExecutionPlan storage plan = _executionPlan[proposalId]; + + uint32 length = plan.length; + delay = plan.delay; + indirect = new bool[](length); + withDelay = new bool[](length); + for (uint256 i = 0; i < length; ++i) { + (indirect[i], withDelay[i], ) = _getManagerData(plan, i); + } + + return (delay, indirect, withDelay); + } + + /// @inheritdoc IGovernor + function proposalNeedsQueuing(uint256 proposalId) public view virtual override returns (bool) { + return _executionPlan[proposalId].delay > 0; + } + + /// @inheritdoc IGovernor + function propose( + address[] memory targets, + uint256[] memory values, + bytes[] memory calldatas, + string memory description + ) public virtual override returns (uint256) { + uint256 proposalId = super.propose(targets, values, calldatas, description); + + uint32 neededDelay = baseDelaySeconds(); + + ExecutionPlan storage plan = _executionPlan[proposalId]; + plan.length = SafeCast.toUint16(targets.length); + + for (uint256 i = 0; i < targets.length; ++i) { + if (calldatas[i].length < 4) { + continue; + } + address target = targets[i]; + bytes4 selector = bytes4(calldatas[i]); + (bool immediate, uint32 delay) = AuthorityUtils.canCallWithDelay( + address(_manager), + address(this), + target, + selector + ); + if ((immediate || delay > 0) && !isAccessManagerIgnored(target, selector)) { + _setManagerData(plan, i, !immediate, 0); + // downcast is safe because both arguments are uint32 + neededDelay = uint32(Math.max(delay, neededDelay)); + } + } + + plan.delay = neededDelay; + + return proposalId; + } + + /** + * @dev Mechanism to queue a proposal, potentially scheduling some of its operations in the AccessManager. + * + * NOTE: The execution delay is chosen based on the delay information retrieved in {propose}. This value may be + * off if the delay was updated since proposal creation. In this case, the proposal needs to be recreated. + */ + function _queueOperations( + uint256 proposalId, + address[] memory targets, + uint256[] memory /* values */, + bytes[] memory calldatas, + bytes32 /* descriptionHash */ + ) internal virtual override returns (uint48) { + ExecutionPlan storage plan = _executionPlan[proposalId]; + uint48 etaSeconds = Time.timestamp() + plan.delay; + + for (uint256 i = 0; i < targets.length; ++i) { + (, bool withDelay, ) = _getManagerData(plan, i); + if (withDelay) { + // This function can reenter when calling `_manager.schedule` before performing state updates in `_setManagerData`. + // However, the `manager` is a trusted contract in the current context's security model (e.g. an `AccessManager`). + // slither-disable-next-line reentrancy-no-eth + (, uint32 nonce) = _manager.schedule(targets[i], calldatas[i], etaSeconds); + _setManagerData(plan, i, true, nonce); + } + } + + return etaSeconds; + } + + /** + * @dev Mechanism to execute a proposal, potentially going through {AccessManager-execute} for delayed operations. + */ + function _executeOperations( + uint256 proposalId, + address[] memory targets, + uint256[] memory values, + bytes[] memory calldatas, + bytes32 /* descriptionHash */ + ) internal virtual override { + uint48 etaSeconds = SafeCast.toUint48(proposalEta(proposalId)); + if (block.timestamp < etaSeconds) { + revert GovernorUnmetDelay(proposalId, etaSeconds); + } + + ExecutionPlan storage plan = _executionPlan[proposalId]; + + for (uint256 i = 0; i < targets.length; ++i) { + (bool controlled, bool withDelay, uint32 nonce) = _getManagerData(plan, i); + if (controlled) { + uint32 executedNonce = _manager.execute{value: values[i]}(targets[i], calldatas[i]); + if (withDelay && executedNonce != nonce) { + revert GovernorMismatchedNonce(proposalId, nonce, executedNonce); + } + } else { + (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]); + Address.verifyCallResult(success, returndata); + } + } + } + + /// @inheritdoc Governor + function _cancel( + address[] memory targets, + uint256[] memory values, + bytes[] memory calldatas, + bytes32 descriptionHash + ) internal virtual override returns (uint256) { + uint256 proposalId = super._cancel(targets, values, calldatas, descriptionHash); + + uint48 etaSeconds = SafeCast.toUint48(proposalEta(proposalId)); + + ExecutionPlan storage plan = _executionPlan[proposalId]; + + // If the proposal has been scheduled it will have an ETA and we may have to externally cancel + if (etaSeconds != 0) { + for (uint256 i = 0; i < targets.length; ++i) { + (, bool withDelay, uint32 nonce) = _getManagerData(plan, i); + // Only attempt to cancel if the execution plan included a delay + if (withDelay) { + bytes32 operationId = _manager.hashOperation(address(this), targets[i], calldatas[i]); + // Check first if the current operation nonce is the one that we observed previously. It could + // already have been cancelled and rescheduled. We don't want to cancel unless it is exactly the + // instance that we previously scheduled. + if (nonce == _manager.getNonce(operationId)) { + // It is important that all calls have an opportunity to be cancelled. We chose to ignore + // potential failures of some of the cancel operations to give the other operations a chance to + // be properly cancelled. In particular cancel might fail if the operation was already cancelled + // by guardians previously. We don't match on the revert reason to avoid encoding assumptions + // about specific errors. + try _manager.cancel(address(this), targets[i], calldatas[i]) {} catch {} + } + } + } + } + + return proposalId; + } + + /** + * @dev Returns whether the operation at an index is delayed by the manager, and its scheduling nonce once queued. + */ + function _getManagerData( + ExecutionPlan storage plan, + uint256 index + ) private view returns (bool controlled, bool withDelay, uint32 nonce) { + (uint256 bucket, uint256 subindex) = _getManagerDataIndices(index); + uint32 value = plan.managerData[bucket][subindex]; + unchecked { + return (value > 0, value > 1, value > 1 ? value - 2 : 0); + } + } + + /** + * @dev Marks an operation at an index as permissioned by the manager, potentially delayed, and + * when delayed sets its scheduling nonce. + */ + function _setManagerData(ExecutionPlan storage plan, uint256 index, bool withDelay, uint32 nonce) private { + (uint256 bucket, uint256 subindex) = _getManagerDataIndices(index); + plan.managerData[bucket][subindex] = withDelay ? nonce + 2 : 1; + } + + /** + * @dev Returns bucket and subindex for reading manager data from the packed array mapping. + */ + function _getManagerDataIndices(uint256 index) private pure returns (uint256 bucket, uint256 subindex) { + bucket = index >> 3; // index / 8 + subindex = index & 7; // index % 8 + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/governance/extensions/GovernorTimelockCompound.sol b/dependencies/@openzeppelin-contracts-5.4.0/governance/extensions/GovernorTimelockCompound.sol new file mode 100644 index 00000000..dce13f1b --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/governance/extensions/GovernorTimelockCompound.sol @@ -0,0 +1,165 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (governance/extensions/GovernorTimelockCompound.sol) + +pragma solidity ^0.8.24; + +import {IGovernor, Governor} from "../Governor.sol"; +import {ICompoundTimelock} from "../../vendor/compound/ICompoundTimelock.sol"; +import {Address} from "../../utils/Address.sol"; +import {SafeCast} from "../../utils/math/SafeCast.sol"; + +/** + * @dev Extension of {Governor} that binds the execution process to a Compound Timelock. This adds a delay, enforced by + * the external timelock to all successful proposals (in addition to the voting duration). The {Governor} needs to be + * the admin of the timelock for any operation to be performed. A public, unrestricted, + * {GovernorTimelockCompound-__acceptAdmin} is available to accept ownership of the timelock. + * + * Using this model means the proposal will be operated by the {TimelockController} and not by the {Governor}. Thus, + * the assets and permissions must be attached to the {TimelockController}. Any asset sent to the {Governor} will be + * inaccessible from a proposal, unless executed via {Governor-relay}. + */ +abstract contract GovernorTimelockCompound is Governor { + ICompoundTimelock private _timelock; + + /** + * @dev Emitted when the timelock controller used for proposal execution is modified. + */ + event TimelockChange(address oldTimelock, address newTimelock); + + /** + * @dev Set the timelock. + */ + constructor(ICompoundTimelock timelockAddress) { + _updateTimelock(timelockAddress); + } + + /** + * @dev Overridden version of the {Governor-state} function with added support for the `Expired` state. + */ + function state(uint256 proposalId) public view virtual override returns (ProposalState) { + ProposalState currentState = super.state(proposalId); + + return + (currentState == ProposalState.Queued && + block.timestamp >= proposalEta(proposalId) + _timelock.GRACE_PERIOD()) + ? ProposalState.Expired + : currentState; + } + + /** + * @dev Public accessor to check the address of the timelock + */ + function timelock() public view virtual returns (address) { + return address(_timelock); + } + + /// @inheritdoc IGovernor + function proposalNeedsQueuing(uint256) public view virtual override returns (bool) { + return true; + } + + /** + * @dev Function to queue a proposal to the timelock. + */ + function _queueOperations( + uint256 proposalId, + address[] memory targets, + uint256[] memory values, + bytes[] memory calldatas, + bytes32 /*descriptionHash*/ + ) internal virtual override returns (uint48) { + uint48 etaSeconds = SafeCast.toUint48(block.timestamp + _timelock.delay()); + + for (uint256 i = 0; i < targets.length; ++i) { + if ( + _timelock.queuedTransactions(keccak256(abi.encode(targets[i], values[i], "", calldatas[i], etaSeconds))) + ) { + revert GovernorAlreadyQueuedProposal(proposalId); + } + _timelock.queueTransaction(targets[i], values[i], "", calldatas[i], etaSeconds); + } + + return etaSeconds; + } + + /** + * @dev Overridden version of the {Governor-_executeOperations} function that run the already queued proposal + * through the timelock. + */ + function _executeOperations( + uint256 proposalId, + address[] memory targets, + uint256[] memory values, + bytes[] memory calldatas, + bytes32 /*descriptionHash*/ + ) internal virtual override { + uint256 etaSeconds = proposalEta(proposalId); + if (etaSeconds == 0) { + revert GovernorNotQueuedProposal(proposalId); + } + Address.sendValue(payable(_timelock), msg.value); + for (uint256 i = 0; i < targets.length; ++i) { + _timelock.executeTransaction(targets[i], values[i], "", calldatas[i], etaSeconds); + } + } + + /** + * @dev Overridden version of the {Governor-_cancel} function to cancel the timelocked proposal if it has already + * been queued. + */ + function _cancel( + address[] memory targets, + uint256[] memory values, + bytes[] memory calldatas, + bytes32 descriptionHash + ) internal virtual override returns (uint256) { + uint256 proposalId = super._cancel(targets, values, calldatas, descriptionHash); + + uint256 etaSeconds = proposalEta(proposalId); + if (etaSeconds > 0) { + // do external call later + for (uint256 i = 0; i < targets.length; ++i) { + _timelock.cancelTransaction(targets[i], values[i], "", calldatas[i], etaSeconds); + } + } + + return proposalId; + } + + /** + * @dev Address through which the governor executes action. In this case, the timelock. + */ + function _executor() internal view virtual override returns (address) { + return address(_timelock); + } + + /** + * @dev Accept admin right over the timelock. + */ + // solhint-disable-next-line private-vars-leading-underscore + function __acceptAdmin() public { + _timelock.acceptAdmin(); + } + + /** + * @dev Public endpoint to update the underlying timelock instance. Restricted to the timelock itself, so updates + * must be proposed, scheduled, and executed through governance proposals. + * + * For security reasons, the timelock must be handed over to another admin before setting up a new one. The two + * operations (hand over the timelock) and do the update can be batched in a single proposal. + * + * Note that if the timelock admin has been handed over in a previous operation, we refuse updates made through the + * timelock if admin of the timelock has already been accepted and the operation is executed outside the scope of + * governance. + + * CAUTION: It is not recommended to change the timelock while there are other queued governance proposals. + */ + function updateTimelock(ICompoundTimelock newTimelock) external virtual onlyGovernance { + _updateTimelock(newTimelock); + } + + function _updateTimelock(ICompoundTimelock newTimelock) private { + emit TimelockChange(address(_timelock), address(newTimelock)); + _timelock = newTimelock; + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/governance/extensions/GovernorTimelockControl.sol b/dependencies/@openzeppelin-contracts-5.4.0/governance/extensions/GovernorTimelockControl.sol new file mode 100644 index 00000000..b3f3b26c --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/governance/extensions/GovernorTimelockControl.sol @@ -0,0 +1,167 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (governance/extensions/GovernorTimelockControl.sol) + +pragma solidity ^0.8.24; + +import {IGovernor, Governor} from "../Governor.sol"; +import {TimelockController} from "../TimelockController.sol"; +import {SafeCast} from "../../utils/math/SafeCast.sol"; + +/** + * @dev Extension of {Governor} that binds the execution process to an instance of {TimelockController}. This adds a + * delay, enforced by the {TimelockController} to all successful proposal (in addition to the voting duration). The + * {Governor} needs the proposer (and ideally the executor and canceller) roles for the {Governor} to work properly. + * + * Using this model means the proposal will be operated by the {TimelockController} and not by the {Governor}. Thus, + * the assets and permissions must be attached to the {TimelockController}. Any asset sent to the {Governor} will be + * inaccessible from a proposal, unless executed via {Governor-relay}. + * + * WARNING: Setting up the TimelockController to have additional proposers or cancelers besides the governor is very + * risky, as it grants them the ability to: 1) execute operations as the timelock, and thus possibly performing + * operations or accessing funds that are expected to only be accessible through a vote, and 2) block governance + * proposals that have been approved by the voters, effectively executing a Denial of Service attack. + */ +abstract contract GovernorTimelockControl is Governor { + TimelockController private _timelock; + mapping(uint256 proposalId => bytes32) private _timelockIds; + + /** + * @dev Emitted when the timelock controller used for proposal execution is modified. + */ + event TimelockChange(address oldTimelock, address newTimelock); + + /** + * @dev Set the timelock. + */ + constructor(TimelockController timelockAddress) { + _updateTimelock(timelockAddress); + } + + /** + * @dev Overridden version of the {Governor-state} function that considers the status reported by the timelock. + */ + function state(uint256 proposalId) public view virtual override returns (ProposalState) { + ProposalState currentState = super.state(proposalId); + + if (currentState != ProposalState.Queued) { + return currentState; + } + + bytes32 queueid = _timelockIds[proposalId]; + if (_timelock.isOperationPending(queueid)) { + return ProposalState.Queued; + } else if (_timelock.isOperationDone(queueid)) { + // This can happen if the proposal is executed directly on the timelock. + return ProposalState.Executed; + } else { + // This can happen if the proposal is canceled directly on the timelock. + return ProposalState.Canceled; + } + } + + /** + * @dev Public accessor to check the address of the timelock + */ + function timelock() public view virtual returns (address) { + return address(_timelock); + } + + /// @inheritdoc IGovernor + function proposalNeedsQueuing(uint256) public view virtual override returns (bool) { + return true; + } + + /** + * @dev Function to queue a proposal to the timelock. + */ + function _queueOperations( + uint256 proposalId, + address[] memory targets, + uint256[] memory values, + bytes[] memory calldatas, + bytes32 descriptionHash + ) internal virtual override returns (uint48) { + uint256 delay = _timelock.getMinDelay(); + + bytes32 salt = _timelockSalt(descriptionHash); + _timelockIds[proposalId] = _timelock.hashOperationBatch(targets, values, calldatas, 0, salt); + _timelock.scheduleBatch(targets, values, calldatas, 0, salt, delay); + + return SafeCast.toUint48(block.timestamp + delay); + } + + /** + * @dev Overridden version of the {Governor-_executeOperations} function that runs the already queued proposal + * through the timelock. + */ + function _executeOperations( + uint256 proposalId, + address[] memory targets, + uint256[] memory values, + bytes[] memory calldatas, + bytes32 descriptionHash + ) internal virtual override { + // execute + _timelock.executeBatch{value: msg.value}(targets, values, calldatas, 0, _timelockSalt(descriptionHash)); + // cleanup for refund + delete _timelockIds[proposalId]; + } + + /** + * @dev Overridden version of the {Governor-_cancel} function to cancel the timelocked proposal if it has already + * been queued. + */ + // This function can reenter through the external call to the timelock, but we assume the timelock is trusted and + // well behaved (according to TimelockController) and this will not happen. + // slither-disable-next-line reentrancy-no-eth + function _cancel( + address[] memory targets, + uint256[] memory values, + bytes[] memory calldatas, + bytes32 descriptionHash + ) internal virtual override returns (uint256) { + uint256 proposalId = super._cancel(targets, values, calldatas, descriptionHash); + + bytes32 timelockId = _timelockIds[proposalId]; + if (timelockId != 0) { + // cancel + _timelock.cancel(timelockId); + // cleanup + delete _timelockIds[proposalId]; + } + + return proposalId; + } + + /** + * @dev Address through which the governor executes action. In this case, the timelock. + */ + function _executor() internal view virtual override returns (address) { + return address(_timelock); + } + + /** + * @dev Public endpoint to update the underlying timelock instance. Restricted to the timelock itself, so updates + * must be proposed, scheduled, and executed through governance proposals. + * + * CAUTION: It is not recommended to change the timelock while there are other queued governance proposals. + */ + function updateTimelock(TimelockController newTimelock) external virtual onlyGovernance { + _updateTimelock(newTimelock); + } + + function _updateTimelock(TimelockController newTimelock) private { + emit TimelockChange(address(_timelock), address(newTimelock)); + _timelock = newTimelock; + } + + /** + * @dev Computes the {TimelockController} operation salt. + * + * It is computed with the governor address itself to avoid collisions across governor instances using the + * same timelock. + */ + function _timelockSalt(bytes32 descriptionHash) private view returns (bytes32) { + return bytes20(address(this)) ^ descriptionHash; + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/governance/extensions/GovernorVotes.sol b/dependencies/@openzeppelin-contracts-5.4.0/governance/extensions/GovernorVotes.sol new file mode 100644 index 00000000..4ad5870a --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/governance/extensions/GovernorVotes.sol @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (governance/extensions/GovernorVotes.sol) + +pragma solidity ^0.8.24; + +import {Governor} from "../Governor.sol"; +import {IVotes} from "../utils/IVotes.sol"; +import {IERC5805} from "../../interfaces/IERC5805.sol"; +import {Time} from "../../utils/types/Time.sol"; + +/** + * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes} + * token. + */ +abstract contract GovernorVotes is Governor { + IERC5805 private immutable _token; + + constructor(IVotes tokenAddress) { + _token = IERC5805(address(tokenAddress)); + } + + /** + * @dev The token that voting power is sourced from. + */ + function token() public view virtual returns (IERC5805) { + return _token; + } + + /** + * @dev Clock (as specified in ERC-6372) is set to match the token's clock. Fallback to block numbers if the token + * does not implement ERC-6372. + */ + function clock() public view virtual override returns (uint48) { + try token().clock() returns (uint48 timepoint) { + return timepoint; + } catch { + return Time.blockNumber(); + } + } + + /** + * @dev Machine-readable description of the clock as specified in ERC-6372. + */ + // solhint-disable-next-line func-name-mixedcase + function CLOCK_MODE() public view virtual override returns (string memory) { + try token().CLOCK_MODE() returns (string memory clockmode) { + return clockmode; + } catch { + return "mode=blocknumber&from=default"; + } + } + + /** + * Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}). + */ + function _getVotes( + address account, + uint256 timepoint, + bytes memory /*params*/ + ) internal view virtual override returns (uint256) { + return token().getPastVotes(account, timepoint); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/governance/extensions/GovernorVotesQuorumFraction.sol b/dependencies/@openzeppelin-contracts-5.4.0/governance/extensions/GovernorVotesQuorumFraction.sol new file mode 100644 index 00000000..2f6034df --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/governance/extensions/GovernorVotesQuorumFraction.sol @@ -0,0 +1,113 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (governance/extensions/GovernorVotesQuorumFraction.sol) + +pragma solidity ^0.8.24; + +import {GovernorVotes} from "./GovernorVotes.sol"; +import {Math} from "../../utils/math/Math.sol"; +import {SafeCast} from "../../utils/math/SafeCast.sol"; +import {Checkpoints} from "../../utils/structs/Checkpoints.sol"; + +/** + * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token and a quorum expressed as a + * fraction of the total supply. + */ +abstract contract GovernorVotesQuorumFraction is GovernorVotes { + using Checkpoints for Checkpoints.Trace208; + + Checkpoints.Trace208 private _quorumNumeratorHistory; + + event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator); + + /** + * @dev The quorum set is not a valid fraction. + */ + error GovernorInvalidQuorumFraction(uint256 quorumNumerator, uint256 quorumDenominator); + + /** + * @dev Initialize quorum as a fraction of the token's total supply. + * + * The fraction is specified as `numerator / denominator`. By default the denominator is 100, so quorum is + * specified as a percent: a numerator of 10 corresponds to quorum being 10% of total supply. The denominator can be + * customized by overriding {quorumDenominator}. + */ + constructor(uint256 quorumNumeratorValue) { + _updateQuorumNumerator(quorumNumeratorValue); + } + + /** + * @dev Returns the current quorum numerator. See {quorumDenominator}. + */ + function quorumNumerator() public view virtual returns (uint256) { + return _quorumNumeratorHistory.latest(); + } + + /** + * @dev Returns the quorum numerator at a specific timepoint. See {quorumDenominator}. + */ + function quorumNumerator(uint256 timepoint) public view virtual returns (uint256) { + return _optimisticUpperLookupRecent(_quorumNumeratorHistory, timepoint); + } + + /** + * @dev Returns the quorum denominator. Defaults to 100, but may be overridden. + */ + function quorumDenominator() public view virtual returns (uint256) { + return 100; + } + + /** + * @dev Returns the quorum for a timepoint, in terms of number of votes: `supply * numerator / denominator`. + */ + function quorum(uint256 timepoint) public view virtual override returns (uint256) { + return Math.mulDiv(token().getPastTotalSupply(timepoint), quorumNumerator(timepoint), quorumDenominator()); + } + + /** + * @dev Changes the quorum numerator. + * + * Emits a {QuorumNumeratorUpdated} event. + * + * Requirements: + * + * - Must be called through a governance proposal. + * - New numerator must be smaller or equal to the denominator. + */ + function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance { + _updateQuorumNumerator(newQuorumNumerator); + } + + /** + * @dev Changes the quorum numerator. + * + * Emits a {QuorumNumeratorUpdated} event. + * + * Requirements: + * + * - New numerator must be smaller or equal to the denominator. + */ + function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual { + uint256 denominator = quorumDenominator(); + if (newQuorumNumerator > denominator) { + revert GovernorInvalidQuorumFraction(newQuorumNumerator, denominator); + } + + uint256 oldQuorumNumerator = quorumNumerator(); + _quorumNumeratorHistory.push(clock(), SafeCast.toUint208(newQuorumNumerator)); + + emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator); + } + + /** + * @dev Returns the numerator at a specific timepoint. + */ + function _optimisticUpperLookupRecent( + Checkpoints.Trace208 storage ckpts, + uint256 timepoint + ) internal view returns (uint256) { + // If trace is empty, key and value are both equal to 0. + // In that case `key <= timepoint` is true, and it is ok to return 0. + (, uint48 key, uint208 value) = ckpts.latestCheckpoint(); + return key <= timepoint ? value : ckpts.upperLookupRecent(SafeCast.toUint48(timepoint)); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/governance/extensions/GovernorVotesSuperQuorumFraction.sol b/dependencies/@openzeppelin-contracts-5.4.0/governance/extensions/GovernorVotesSuperQuorumFraction.sol new file mode 100644 index 00000000..1c47840b --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/governance/extensions/GovernorVotesSuperQuorumFraction.sol @@ -0,0 +1,134 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (governance/extensions/GovernorVotesSuperQuorumFraction.sol) +pragma solidity ^0.8.24; + +import {Governor} from "../Governor.sol"; +import {GovernorSuperQuorum} from "./GovernorSuperQuorum.sol"; +import {GovernorVotesQuorumFraction} from "./GovernorVotesQuorumFraction.sol"; +import {Math} from "../../utils/math/Math.sol"; +import {SafeCast} from "../../utils/math/SafeCast.sol"; +import {Checkpoints} from "../../utils/structs/Checkpoints.sol"; + +/** + * @dev Extension of {GovernorVotesQuorumFraction} with a super quorum expressed as a + * fraction of the total supply. Proposals that meet the super quorum (and have a majority of for votes) advance to + * the `Succeeded` state before the proposal deadline. + */ +abstract contract GovernorVotesSuperQuorumFraction is GovernorVotesQuorumFraction, GovernorSuperQuorum { + using Checkpoints for Checkpoints.Trace208; + + Checkpoints.Trace208 private _superQuorumNumeratorHistory; + + event SuperQuorumNumeratorUpdated(uint256 oldSuperQuorumNumerator, uint256 newSuperQuorumNumerator); + + /** + * @dev The super quorum set is not valid as it exceeds the quorum denominator. + */ + error GovernorInvalidSuperQuorumFraction(uint256 superQuorumNumerator, uint256 denominator); + + /** + * @dev The super quorum set is not valid as it is smaller or equal to the quorum. + */ + error GovernorInvalidSuperQuorumTooSmall(uint256 superQuorumNumerator, uint256 quorumNumerator); + + /** + * @dev The quorum set is not valid as it exceeds the super quorum. + */ + error GovernorInvalidQuorumTooLarge(uint256 quorumNumerator, uint256 superQuorumNumerator); + + /** + * @dev Initialize super quorum as a fraction of the token's total supply. + * + * The super quorum is specified as a fraction of the token's total supply and has to + * be greater than the quorum. + */ + constructor(uint256 superQuorumNumeratorValue) { + _updateSuperQuorumNumerator(superQuorumNumeratorValue); + } + + /** + * @dev Returns the current super quorum numerator. + */ + function superQuorumNumerator() public view virtual returns (uint256) { + return _superQuorumNumeratorHistory.latest(); + } + + /** + * @dev Returns the super quorum numerator at a specific `timepoint`. + */ + function superQuorumNumerator(uint256 timepoint) public view virtual returns (uint256) { + return _optimisticUpperLookupRecent(_superQuorumNumeratorHistory, timepoint); + } + + /** + * @dev Returns the super quorum for a `timepoint`, in terms of number of votes: `supply * numerator / denominator`. + * See {GovernorSuperQuorum-superQuorum} for more details. + */ + function superQuorum(uint256 timepoint) public view virtual override returns (uint256) { + return Math.mulDiv(token().getPastTotalSupply(timepoint), superQuorumNumerator(timepoint), quorumDenominator()); + } + + /** + * @dev Changes the super quorum numerator. + * + * Emits a {SuperQuorumNumeratorUpdated} event. + * + * Requirements: + * + * - Must be called through a governance proposal. + * - New super quorum numerator must be smaller or equal to the denominator. + * - New super quorum numerator must be greater than or equal to the quorum numerator. + */ + function updateSuperQuorumNumerator(uint256 newSuperQuorumNumerator) public virtual onlyGovernance { + _updateSuperQuorumNumerator(newSuperQuorumNumerator); + } + + /** + * @dev Changes the super quorum numerator. + * + * Emits a {SuperQuorumNumeratorUpdated} event. + * + * Requirements: + * + * - New super quorum numerator must be smaller or equal to the denominator. + * - New super quorum numerator must be greater than or equal to the quorum numerator. + */ + function _updateSuperQuorumNumerator(uint256 newSuperQuorumNumerator) internal virtual { + uint256 denominator = quorumDenominator(); + if (newSuperQuorumNumerator > denominator) { + revert GovernorInvalidSuperQuorumFraction(newSuperQuorumNumerator, denominator); + } + + uint256 quorumNumerator = quorumNumerator(); + if (newSuperQuorumNumerator < quorumNumerator) { + revert GovernorInvalidSuperQuorumTooSmall(newSuperQuorumNumerator, quorumNumerator); + } + + uint256 oldSuperQuorumNumerator = _superQuorumNumeratorHistory.latest(); + _superQuorumNumeratorHistory.push(clock(), SafeCast.toUint208(newSuperQuorumNumerator)); + + emit SuperQuorumNumeratorUpdated(oldSuperQuorumNumerator, newSuperQuorumNumerator); + } + + /** + * @dev Overrides {GovernorVotesQuorumFraction-_updateQuorumNumerator} to ensure the super + * quorum numerator is greater than or equal to the quorum numerator. + */ + function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual override { + // Ignoring check when the superQuorum was never set (construction sets quorum before superQuorum) + if (_superQuorumNumeratorHistory.length() > 0) { + uint256 superQuorumNumerator_ = superQuorumNumerator(); + if (newQuorumNumerator > superQuorumNumerator_) { + revert GovernorInvalidQuorumTooLarge(newQuorumNumerator, superQuorumNumerator_); + } + } + super._updateQuorumNumerator(newQuorumNumerator); + } + + /// @inheritdoc GovernorSuperQuorum + function state( + uint256 proposalId + ) public view virtual override(Governor, GovernorSuperQuorum) returns (ProposalState) { + return super.state(proposalId); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/governance/utils/IVotes.sol b/dependencies/@openzeppelin-contracts-5.4.0/governance/utils/IVotes.sol new file mode 100644 index 00000000..a007f3a7 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/governance/utils/IVotes.sol @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (governance/utils/IVotes.sol) +pragma solidity >=0.8.4; + +/** + * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts. + */ +interface IVotes { + /** + * @dev The signature used has expired. + */ + error VotesExpiredSignature(uint256 expiry); + + /** + * @dev Emitted when an account changes their delegate. + */ + event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate); + + /** + * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of voting units. + */ + event DelegateVotesChanged(address indexed delegate, uint256 previousVotes, uint256 newVotes); + + /** + * @dev Returns the current amount of votes that `account` has. + */ + function getVotes(address account) external view returns (uint256); + + /** + * @dev Returns the amount of votes that `account` had at a specific moment in the past. If the `clock()` is + * configured to use block numbers, this will return the value at the end of the corresponding block. + */ + function getPastVotes(address account, uint256 timepoint) external view returns (uint256); + + /** + * @dev Returns the total supply of votes available at a specific moment in the past. If the `clock()` is + * configured to use block numbers, this will return the value at the end of the corresponding block. + * + * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes. + * Votes that have not been delegated are still part of total supply, even though they would not participate in a + * vote. + */ + function getPastTotalSupply(uint256 timepoint) external view returns (uint256); + + /** + * @dev Returns the delegate that `account` has chosen. + */ + function delegates(address account) external view returns (address); + + /** + * @dev Delegates votes from the sender to `delegatee`. + */ + function delegate(address delegatee) external; + + /** + * @dev Delegates votes from signer to `delegatee`. + */ + function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external; +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/governance/utils/Votes.sol b/dependencies/@openzeppelin-contracts-5.4.0/governance/utils/Votes.sol new file mode 100644 index 00000000..f5994f2b --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/governance/utils/Votes.sol @@ -0,0 +1,252 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.2.0) (governance/utils/Votes.sol) +pragma solidity ^0.8.20; + +import {IERC5805} from "../../interfaces/IERC5805.sol"; +import {Context} from "../../utils/Context.sol"; +import {Nonces} from "../../utils/Nonces.sol"; +import {EIP712} from "../../utils/cryptography/EIP712.sol"; +import {Checkpoints} from "../../utils/structs/Checkpoints.sol"; +import {SafeCast} from "../../utils/math/SafeCast.sol"; +import {ECDSA} from "../../utils/cryptography/ECDSA.sol"; +import {Time} from "../../utils/types/Time.sol"; + +/** + * @dev This is a base abstract contract that tracks voting units, which are a measure of voting power that can be + * transferred, and provides a system of vote delegation, where an account can delegate its voting units to a sort of + * "representative" that will pool delegated voting units from different accounts and can then use it to vote in + * decisions. In fact, voting units _must_ be delegated in order to count as actual votes, and an account has to + * delegate those votes to itself if it wishes to participate in decisions and does not have a trusted representative. + * + * This contract is often combined with a token contract such that voting units correspond to token units. For an + * example, see {ERC721Votes}. + * + * The full history of delegate votes is tracked on-chain so that governance protocols can consider votes as distributed + * at a particular block number to protect against flash loans and double voting. The opt-in delegate system makes the + * cost of this history tracking optional. + * + * When using this module the derived contract must implement {_getVotingUnits} (for example, make it return + * {ERC721-balanceOf}), and can use {_transferVotingUnits} to track a change in the distribution of those units (in the + * previous example, it would be included in {ERC721-_update}). + */ +abstract contract Votes is Context, EIP712, Nonces, IERC5805 { + using Checkpoints for Checkpoints.Trace208; + + bytes32 private constant DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address account => address) private _delegatee; + + mapping(address delegatee => Checkpoints.Trace208) private _delegateCheckpoints; + + Checkpoints.Trace208 private _totalCheckpoints; + + /** + * @dev The clock was incorrectly modified. + */ + error ERC6372InconsistentClock(); + + /** + * @dev Lookup to future votes is not available. + */ + error ERC5805FutureLookup(uint256 timepoint, uint48 clock); + + /** + * @dev Clock used for flagging checkpoints. Can be overridden to implement timestamp based + * checkpoints (and voting), in which case {CLOCK_MODE} should be overridden as well to match. + */ + function clock() public view virtual returns (uint48) { + return Time.blockNumber(); + } + + /** + * @dev Machine-readable description of the clock as specified in ERC-6372. + */ + // solhint-disable-next-line func-name-mixedcase + function CLOCK_MODE() public view virtual returns (string memory) { + // Check that the clock was not modified + if (clock() != Time.blockNumber()) { + revert ERC6372InconsistentClock(); + } + return "mode=blocknumber&from=default"; + } + + /** + * @dev Validate that a timepoint is in the past, and return it as a uint48. + */ + function _validateTimepoint(uint256 timepoint) internal view returns (uint48) { + uint48 currentTimepoint = clock(); + if (timepoint >= currentTimepoint) revert ERC5805FutureLookup(timepoint, currentTimepoint); + return SafeCast.toUint48(timepoint); + } + + /** + * @dev Returns the current amount of votes that `account` has. + */ + function getVotes(address account) public view virtual returns (uint256) { + return _delegateCheckpoints[account].latest(); + } + + /** + * @dev Returns the amount of votes that `account` had at a specific moment in the past. If the `clock()` is + * configured to use block numbers, this will return the value at the end of the corresponding block. + * + * Requirements: + * + * - `timepoint` must be in the past. If operating using block numbers, the block must be already mined. + */ + function getPastVotes(address account, uint256 timepoint) public view virtual returns (uint256) { + return _delegateCheckpoints[account].upperLookupRecent(_validateTimepoint(timepoint)); + } + + /** + * @dev Returns the total supply of votes available at a specific moment in the past. If the `clock()` is + * configured to use block numbers, this will return the value at the end of the corresponding block. + * + * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes. + * Votes that have not been delegated are still part of total supply, even though they would not participate in a + * vote. + * + * Requirements: + * + * - `timepoint` must be in the past. If operating using block numbers, the block must be already mined. + */ + function getPastTotalSupply(uint256 timepoint) public view virtual returns (uint256) { + return _totalCheckpoints.upperLookupRecent(_validateTimepoint(timepoint)); + } + + /** + * @dev Returns the current total supply of votes. + */ + function _getTotalSupply() internal view virtual returns (uint256) { + return _totalCheckpoints.latest(); + } + + /** + * @dev Returns the delegate that `account` has chosen. + */ + function delegates(address account) public view virtual returns (address) { + return _delegatee[account]; + } + + /** + * @dev Delegates votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual { + address account = _msgSender(); + _delegate(account, delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee`. + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual { + if (block.timestamp > expiry) { + revert VotesExpiredSignature(expiry); + } + address signer = ECDSA.recover( + _hashTypedDataV4(keccak256(abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + _useCheckedNonce(signer, nonce); + _delegate(signer, delegatee); + } + + /** + * @dev Delegate all of `account`'s voting units to `delegatee`. + * + * Emits events {IVotes-DelegateChanged} and {IVotes-DelegateVotesChanged}. + */ + function _delegate(address account, address delegatee) internal virtual { + address oldDelegate = delegates(account); + _delegatee[account] = delegatee; + + emit DelegateChanged(account, oldDelegate, delegatee); + _moveDelegateVotes(oldDelegate, delegatee, _getVotingUnits(account)); + } + + /** + * @dev Transfers, mints, or burns voting units. To register a mint, `from` should be zero. To register a burn, `to` + * should be zero. Total supply of voting units will be adjusted with mints and burns. + */ + function _transferVotingUnits(address from, address to, uint256 amount) internal virtual { + if (from == address(0)) { + _push(_totalCheckpoints, _add, SafeCast.toUint208(amount)); + } + if (to == address(0)) { + _push(_totalCheckpoints, _subtract, SafeCast.toUint208(amount)); + } + _moveDelegateVotes(delegates(from), delegates(to), amount); + } + + /** + * @dev Moves delegated votes from one delegate to another. + */ + function _moveDelegateVotes(address from, address to, uint256 amount) internal virtual { + if (from != to && amount > 0) { + if (from != address(0)) { + (uint256 oldValue, uint256 newValue) = _push( + _delegateCheckpoints[from], + _subtract, + SafeCast.toUint208(amount) + ); + emit DelegateVotesChanged(from, oldValue, newValue); + } + if (to != address(0)) { + (uint256 oldValue, uint256 newValue) = _push( + _delegateCheckpoints[to], + _add, + SafeCast.toUint208(amount) + ); + emit DelegateVotesChanged(to, oldValue, newValue); + } + } + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function _numCheckpoints(address account) internal view virtual returns (uint32) { + return SafeCast.toUint32(_delegateCheckpoints[account].length()); + } + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function _checkpoints( + address account, + uint32 pos + ) internal view virtual returns (Checkpoints.Checkpoint208 memory) { + return _delegateCheckpoints[account].at(pos); + } + + function _push( + Checkpoints.Trace208 storage store, + function(uint208, uint208) view returns (uint208) op, + uint208 delta + ) private returns (uint208 oldValue, uint208 newValue) { + return store.push(clock(), op(store.latest(), delta)); + } + + function _add(uint208 a, uint208 b) private pure returns (uint208) { + return a + b; + } + + function _subtract(uint208 a, uint208 b) private pure returns (uint208) { + return a - b; + } + + /** + * @dev Must return the voting units held by an account. + */ + function _getVotingUnits(address) internal view virtual returns (uint256); +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/governance/utils/VotesExtended.sol b/dependencies/@openzeppelin-contracts-5.4.0/governance/utils/VotesExtended.sol new file mode 100644 index 00000000..5b673203 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/governance/utils/VotesExtended.sol @@ -0,0 +1,84 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.2.0) (governance/utils/VotesExtended.sol) +pragma solidity ^0.8.20; + +import {Checkpoints} from "../../utils/structs/Checkpoints.sol"; +import {Votes} from "./Votes.sol"; +import {SafeCast} from "../../utils/math/SafeCast.sol"; + +/** + * @dev Extension of {Votes} that adds checkpoints for delegations and balances. + * + * WARNING: While this contract extends {Votes}, valid uses of {Votes} may not be compatible with + * {VotesExtended} without additional considerations. This implementation of {_transferVotingUnits} must + * run AFTER the voting weight movement is registered, such that it is reflected on {_getVotingUnits}. + * + * Said differently, {VotesExtended} MUST be integrated in a way that calls {_transferVotingUnits} AFTER the + * asset transfer is registered and balances are updated: + * + * ```solidity + * contract VotingToken is Token, VotesExtended { + * function transfer(address from, address to, uint256 tokenId) public override { + * super.transfer(from, to, tokenId); // <- Perform the transfer first ... + * _transferVotingUnits(from, to, 1); // <- ... then call _transferVotingUnits. + * } + * + * function _getVotingUnits(address account) internal view override returns (uint256) { + * return balanceOf(account); + * } + * } + * ``` + * + * {ERC20Votes} and {ERC721Votes} follow this pattern and are thus safe to use with {VotesExtended}. + */ +abstract contract VotesExtended is Votes { + using Checkpoints for Checkpoints.Trace160; + using Checkpoints for Checkpoints.Trace208; + + mapping(address delegator => Checkpoints.Trace160) private _userDelegationCheckpoints; + mapping(address account => Checkpoints.Trace208) private _userVotingUnitsCheckpoints; + + /** + * @dev Returns the delegate of an `account` at a specific moment in the past. If the `clock()` is + * configured to use block numbers, this will return the value at the end of the corresponding block. + * + * Requirements: + * + * - `timepoint` must be in the past. If operating using block numbers, the block must be already mined. + */ + function getPastDelegate(address account, uint256 timepoint) public view virtual returns (address) { + return address(_userDelegationCheckpoints[account].upperLookupRecent(_validateTimepoint(timepoint))); + } + + /** + * @dev Returns the `balanceOf` of an `account` at a specific moment in the past. If the `clock()` is + * configured to use block numbers, this will return the value at the end of the corresponding block. + * + * Requirements: + * + * - `timepoint` must be in the past. If operating using block numbers, the block must be already mined. + */ + function getPastBalanceOf(address account, uint256 timepoint) public view virtual returns (uint256) { + return _userVotingUnitsCheckpoints[account].upperLookupRecent(_validateTimepoint(timepoint)); + } + + /// @inheritdoc Votes + function _delegate(address account, address delegatee) internal virtual override { + super._delegate(account, delegatee); + + _userDelegationCheckpoints[account].push(clock(), uint160(delegatee)); + } + + /// @inheritdoc Votes + function _transferVotingUnits(address from, address to, uint256 amount) internal virtual override { + super._transferVotingUnits(from, to, amount); + if (from != to) { + if (from != address(0)) { + _userVotingUnitsCheckpoints[from].push(clock(), SafeCast.toUint208(_getVotingUnits(from))); + } + if (to != address(0)) { + _userVotingUnitsCheckpoints[to].push(clock(), SafeCast.toUint208(_getVotingUnits(to))); + } + } + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC1155.sol b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC1155.sol new file mode 100644 index 00000000..6c10b872 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC1155.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC1155.sol) + +pragma solidity >=0.6.2; + +import {IERC1155} from "../token/ERC1155/IERC1155.sol"; diff --git a/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC1155MetadataURI.sol b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC1155MetadataURI.sol new file mode 100644 index 00000000..95f815f4 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC1155MetadataURI.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC1155MetadataURI.sol) + +pragma solidity >=0.6.2; + +import {IERC1155MetadataURI} from "../token/ERC1155/extensions/IERC1155MetadataURI.sol"; diff --git a/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC1155Receiver.sol b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC1155Receiver.sol new file mode 100644 index 00000000..b56bdfef --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC1155Receiver.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC1155Receiver.sol) + +pragma solidity >=0.6.2; + +import {IERC1155Receiver} from "../token/ERC1155/IERC1155Receiver.sol"; diff --git a/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC1271.sol b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC1271.sol new file mode 100644 index 00000000..4382286a --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC1271.sol @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC1271.sol) + +pragma solidity >=0.5.0; + +/** + * @dev Interface of the ERC-1271 standard signature validation method for + * contracts as defined in https://eips.ethereum.org/EIPS/eip-1271[ERC-1271]. + */ +interface IERC1271 { + /** + * @dev Should return whether the signature provided is valid for the provided data + * @param hash Hash of the data to be signed + * @param signature Signature byte array associated with `hash` + */ + function isValidSignature(bytes32 hash, bytes calldata signature) external view returns (bytes4 magicValue); +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC1363.sol b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC1363.sol new file mode 100644 index 00000000..7bf3e1f7 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC1363.sol @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC1363.sol) + +pragma solidity >=0.6.2; + +import {IERC20} from "./IERC20.sol"; +import {IERC165} from "./IERC165.sol"; + +/** + * @title IERC1363 + * @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363]. + * + * Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract + * after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction. + */ +interface IERC1363 is IERC20, IERC165 { + /* + * Note: the ERC-165 identifier for this interface is 0xb0202a11. + * 0xb0202a11 === + * bytes4(keccak256('transferAndCall(address,uint256)')) ^ + * bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^ + * bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^ + * bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^ + * bytes4(keccak256('approveAndCall(address,uint256)')) ^ + * bytes4(keccak256('approveAndCall(address,uint256,bytes)')) + */ + + /** + * @dev Moves a `value` amount of tokens from the caller's account to `to` + * and then calls {IERC1363Receiver-onTransferReceived} on `to`. + * @param to The address which you want to transfer to. + * @param value The amount of tokens to be transferred. + * @return A boolean value indicating whether the operation succeeded unless throwing. + */ + function transferAndCall(address to, uint256 value) external returns (bool); + + /** + * @dev Moves a `value` amount of tokens from the caller's account to `to` + * and then calls {IERC1363Receiver-onTransferReceived} on `to`. + * @param to The address which you want to transfer to. + * @param value The amount of tokens to be transferred. + * @param data Additional data with no specified format, sent in call to `to`. + * @return A boolean value indicating whether the operation succeeded unless throwing. + */ + function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool); + + /** + * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism + * and then calls {IERC1363Receiver-onTransferReceived} on `to`. + * @param from The address which you want to send tokens from. + * @param to The address which you want to transfer to. + * @param value The amount of tokens to be transferred. + * @return A boolean value indicating whether the operation succeeded unless throwing. + */ + function transferFromAndCall(address from, address to, uint256 value) external returns (bool); + + /** + * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism + * and then calls {IERC1363Receiver-onTransferReceived} on `to`. + * @param from The address which you want to send tokens from. + * @param to The address which you want to transfer to. + * @param value The amount of tokens to be transferred. + * @param data Additional data with no specified format, sent in call to `to`. + * @return A boolean value indicating whether the operation succeeded unless throwing. + */ + function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool); + + /** + * @dev Sets a `value` amount of tokens as the allowance of `spender` over the + * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`. + * @param spender The address which will spend the funds. + * @param value The amount of tokens to be spent. + * @return A boolean value indicating whether the operation succeeded unless throwing. + */ + function approveAndCall(address spender, uint256 value) external returns (bool); + + /** + * @dev Sets a `value` amount of tokens as the allowance of `spender` over the + * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`. + * @param spender The address which will spend the funds. + * @param value The amount of tokens to be spent. + * @param data Additional data with no specified format, sent in call to `spender`. + * @return A boolean value indicating whether the operation succeeded unless throwing. + */ + function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool); +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC1363Receiver.sol b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC1363Receiver.sol new file mode 100644 index 00000000..43efc9bf --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC1363Receiver.sol @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC1363Receiver.sol) + +pragma solidity >=0.5.0; + +/** + * @title IERC1363Receiver + * @dev Interface for any contract that wants to support `transferAndCall` or `transferFromAndCall` + * from ERC-1363 token contracts. + */ +interface IERC1363Receiver { + /** + * @dev Whenever ERC-1363 tokens are transferred to this contract via `transferAndCall` or `transferFromAndCall` + * by `operator` from `from`, this function is called. + * + * NOTE: To accept the transfer, this must return + * `bytes4(keccak256("onTransferReceived(address,address,uint256,bytes)"))` + * (i.e. 0x88a7ca5c, or its own function selector). + * + * @param operator The address which called `transferAndCall` or `transferFromAndCall` function. + * @param from The address which the tokens are transferred from. + * @param value The amount of tokens transferred. + * @param data Additional data with no specified format. + * @return `bytes4(keccak256("onTransferReceived(address,address,uint256,bytes)"))` if transfer is allowed unless throwing. + */ + function onTransferReceived( + address operator, + address from, + uint256 value, + bytes calldata data + ) external returns (bytes4); +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC1363Spender.sol b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC1363Spender.sol new file mode 100644 index 00000000..46efa881 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC1363Spender.sol @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC1363Spender.sol) + +pragma solidity >=0.5.0; + +/** + * @title IERC1363Spender + * @dev Interface for any contract that wants to support `approveAndCall` + * from ERC-1363 token contracts. + */ +interface IERC1363Spender { + /** + * @dev Whenever an ERC-1363 token `owner` approves this contract via `approveAndCall` + * to spend their tokens, this function is called. + * + * NOTE: To accept the approval, this must return + * `bytes4(keccak256("onApprovalReceived(address,uint256,bytes)"))` + * (i.e. 0x7b04a2d0, or its own function selector). + * + * @param owner The address which called `approveAndCall` function and previously owned the tokens. + * @param value The amount of tokens to be spent. + * @param data Additional data with no specified format. + * @return `bytes4(keccak256("onApprovalReceived(address,uint256,bytes)"))` if approval is allowed unless throwing. + */ + function onApprovalReceived(address owner, uint256 value, bytes calldata data) external returns (bytes4); +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC165.sol b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC165.sol new file mode 100644 index 00000000..d2c99a5b --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC165.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC165.sol) + +pragma solidity >=0.4.16; + +import {IERC165} from "../utils/introspection/IERC165.sol"; diff --git a/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC1820Implementer.sol b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC1820Implementer.sol new file mode 100644 index 00000000..8c047198 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC1820Implementer.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC1820Implementer.sol) + +pragma solidity >=0.4.16; + +/** + * @dev Interface for an ERC-1820 implementer, as defined in the + * https://eips.ethereum.org/EIPS/eip-1820#interface-implementation-erc1820implementerinterface[ERC]. + * Used by contracts that will be registered as implementers in the + * {IERC1820Registry}. + */ +interface IERC1820Implementer { + /** + * @dev Returns a special value (`ERC1820_ACCEPT_MAGIC`) if this contract + * implements `interfaceHash` for `account`. + * + * See {IERC1820Registry-setInterfaceImplementer}. + */ + function canImplementInterfaceForAddress(bytes32 interfaceHash, address account) external view returns (bytes32); +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC1820Registry.sol b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC1820Registry.sol new file mode 100644 index 00000000..03efa038 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC1820Registry.sol @@ -0,0 +1,112 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC1820Registry.sol) + +pragma solidity >=0.5.0; + +/** + * @dev Interface of the global ERC-1820 Registry, as defined in the + * https://eips.ethereum.org/EIPS/eip-1820[ERC]. Accounts may register + * implementers for interfaces in this registry, as well as query support. + * + * Implementers may be shared by multiple accounts, and can also implement more + * than a single interface for each account. Contracts can implement interfaces + * for themselves, but externally-owned accounts (EOA) must delegate this to a + * contract. + * + * {IERC165} interfaces can also be queried via the registry. + * + * For an in-depth explanation and source code analysis, see the ERC text. + */ +interface IERC1820Registry { + event InterfaceImplementerSet(address indexed account, bytes32 indexed interfaceHash, address indexed implementer); + + event ManagerChanged(address indexed account, address indexed newManager); + + /** + * @dev Sets `newManager` as the manager for `account`. A manager of an + * account is able to set interface implementers for it. + * + * By default, each account is its own manager. Passing a value of `0x0` in + * `newManager` will reset the manager to this initial state. + * + * Emits a {ManagerChanged} event. + * + * Requirements: + * + * - the caller must be the current manager for `account`. + */ + function setManager(address account, address newManager) external; + + /** + * @dev Returns the manager for `account`. + * + * See {setManager}. + */ + function getManager(address account) external view returns (address); + + /** + * @dev Sets the `implementer` contract as ``account``'s implementer for + * `interfaceHash`. + * + * `account` being the zero address is an alias for the caller's address. + * The zero address can also be used in `implementer` to remove an old one. + * + * See {interfaceHash} to learn how these are created. + * + * Emits an {InterfaceImplementerSet} event. + * + * Requirements: + * + * - the caller must be the current manager for `account`. + * - `interfaceHash` must not be an {IERC165} interface id (i.e. it must not + * end in 28 zeroes). + * - `implementer` must implement {IERC1820Implementer} and return true when + * queried for support, unless `implementer` is the caller. See + * {IERC1820Implementer-canImplementInterfaceForAddress}. + */ + function setInterfaceImplementer(address account, bytes32 _interfaceHash, address implementer) external; + + /** + * @dev Returns the implementer of `interfaceHash` for `account`. If no such + * implementer is registered, returns the zero address. + * + * If `interfaceHash` is an {IERC165} interface id (i.e. it ends with 28 + * zeroes), `account` will be queried for support of it. + * + * `account` being the zero address is an alias for the caller's address. + */ + function getInterfaceImplementer(address account, bytes32 _interfaceHash) external view returns (address); + + /** + * @dev Returns the interface hash for an `interfaceName`, as defined in the + * corresponding + * https://eips.ethereum.org/EIPS/eip-1820#interface-name[section of the ERC]. + */ + function interfaceHash(string calldata interfaceName) external pure returns (bytes32); + + /** + * @notice Updates the cache with whether the contract implements an ERC-165 interface or not. + * @param account Address of the contract for which to update the cache. + * @param interfaceId ERC-165 interface for which to update the cache. + */ + function updateERC165Cache(address account, bytes4 interfaceId) external; + + /** + * @notice Checks whether a contract implements an ERC-165 interface or not. + * If the result is not cached a direct lookup on the contract address is performed. + * If the result is not cached or the cached value is out-of-date, the cache MUST be updated manually by calling + * {updateERC165Cache} with the contract address. + * @param account Address of the contract to check. + * @param interfaceId ERC-165 interface to check. + * @return True if `account` implements `interfaceId`, false otherwise. + */ + function implementsERC165Interface(address account, bytes4 interfaceId) external view returns (bool); + + /** + * @notice Checks whether a contract implements an ERC-165 interface or not without using or updating the cache. + * @param account Address of the contract to check. + * @param interfaceId ERC-165 interface to check. + * @return True if `account` implements `interfaceId`, false otherwise. + */ + function implementsERC165InterfaceNoCache(address account, bytes4 interfaceId) external view returns (bool); +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC1967.sol b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC1967.sol new file mode 100644 index 00000000..95d222ec --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC1967.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC1967.sol) + +pragma solidity >=0.4.11; + +/** + * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC. + */ +interface IERC1967 { + /** + * @dev Emitted when the implementation is upgraded. + */ + event Upgraded(address indexed implementation); + + /** + * @dev Emitted when the admin account has changed. + */ + event AdminChanged(address previousAdmin, address newAdmin); + + /** + * @dev Emitted when the beacon is changed. + */ + event BeaconUpgraded(address indexed beacon); +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC20.sol b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC20.sol new file mode 100644 index 00000000..078e9ec9 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC20.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC20.sol) + +pragma solidity >=0.4.16; + +import {IERC20} from "../token/ERC20/IERC20.sol"; diff --git a/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC20Metadata.sol b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC20Metadata.sol new file mode 100644 index 00000000..adffeb5f --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC20Metadata.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC20Metadata.sol) + +pragma solidity >=0.6.2; + +import {IERC20Metadata} from "../token/ERC20/extensions/IERC20Metadata.sol"; diff --git a/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC2309.sol b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC2309.sol new file mode 100644 index 00000000..bc0fb646 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC2309.sol @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC2309.sol) + +pragma solidity >=0.4.11; + +/** + * @dev ERC-2309: ERC-721 Consecutive Transfer Extension. + */ +interface IERC2309 { + /** + * @dev Emitted when the tokens from `fromTokenId` to `toTokenId` are transferred from `fromAddress` to `toAddress`. + */ + event ConsecutiveTransfer( + uint256 indexed fromTokenId, + uint256 toTokenId, + address indexed fromAddress, + address indexed toAddress + ); +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC2612.sol b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC2612.sol new file mode 100644 index 00000000..330c064a --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC2612.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC2612.sol) + +pragma solidity >=0.6.2; + +import {IERC20Permit} from "../token/ERC20/extensions/IERC20Permit.sol"; + +interface IERC2612 is IERC20Permit {} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC2981.sol b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC2981.sol new file mode 100644 index 00000000..858713b8 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC2981.sol @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC2981.sol) + +pragma solidity >=0.6.2; + +import {IERC165} from "../utils/introspection/IERC165.sol"; + +/** + * @dev Interface for the NFT Royalty Standard. + * + * A standardized way to retrieve royalty payment information for non-fungible tokens (NFTs) to enable universal + * support for royalty payments across all NFT marketplaces and ecosystem participants. + */ +interface IERC2981 is IERC165 { + /** + * @dev Returns how much royalty is owed and to whom, based on a sale price that may be denominated in any unit of + * exchange. The royalty amount is denominated and should be paid in that same unit of exchange. + * + * NOTE: ERC-2981 allows setting the royalty to 100% of the price. In that case all the price would be sent to the + * royalty receiver and 0 tokens to the seller. Contracts dealing with royalty should consider empty transfers. + */ + function royaltyInfo( + uint256 tokenId, + uint256 salePrice + ) external view returns (address receiver, uint256 royaltyAmount); +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC3156.sol b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC3156.sol new file mode 100644 index 00000000..95b4b2d8 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC3156.sol @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC3156.sol) + +pragma solidity >=0.5.0; + +import {IERC3156FlashBorrower} from "./IERC3156FlashBorrower.sol"; +import {IERC3156FlashLender} from "./IERC3156FlashLender.sol"; diff --git a/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC3156FlashBorrower.sol b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC3156FlashBorrower.sol new file mode 100644 index 00000000..5028df8d --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC3156FlashBorrower.sol @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC3156FlashBorrower.sol) + +pragma solidity >=0.5.0; + +/** + * @dev Interface of the ERC-3156 FlashBorrower, as defined in + * https://eips.ethereum.org/EIPS/eip-3156[ERC-3156]. + */ +interface IERC3156FlashBorrower { + /** + * @dev Receive a flash loan. + * @param initiator The initiator of the loan. + * @param token The loan currency. + * @param amount The amount of tokens lent. + * @param fee The additional amount of tokens to repay. + * @param data Arbitrary data structure, intended to contain user-defined parameters. + * @return The keccak256 hash of "ERC3156FlashBorrower.onFlashLoan" + */ + function onFlashLoan( + address initiator, + address token, + uint256 amount, + uint256 fee, + bytes calldata data + ) external returns (bytes32); +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC3156FlashLender.sol b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC3156FlashLender.sol new file mode 100644 index 00000000..77ca98ad --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC3156FlashLender.sol @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC3156FlashLender.sol) + +pragma solidity >=0.5.0; + +import {IERC3156FlashBorrower} from "./IERC3156FlashBorrower.sol"; + +/** + * @dev Interface of the ERC-3156 FlashLender, as defined in + * https://eips.ethereum.org/EIPS/eip-3156[ERC-3156]. + */ +interface IERC3156FlashLender { + /** + * @dev The amount of currency available to be lended. + * @param token The loan currency. + * @return The amount of `token` that can be borrowed. + */ + function maxFlashLoan(address token) external view returns (uint256); + + /** + * @dev The fee to be charged for a given loan. + * @param token The loan currency. + * @param amount The amount of tokens lent. + * @return The amount of `token` to be charged for the loan, on top of the returned principal. + */ + function flashFee(address token, uint256 amount) external view returns (uint256); + + /** + * @dev Initiate a flash loan. + * @param receiver The receiver of the tokens in the loan, and the receiver of the callback. + * @param token The loan currency. + * @param amount The amount of tokens lent. + * @param data Arbitrary data structure, intended to contain user-defined parameters. + */ + function flashLoan( + IERC3156FlashBorrower receiver, + address token, + uint256 amount, + bytes calldata data + ) external returns (bool); +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC4626.sol b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC4626.sol new file mode 100644 index 00000000..5f785c3f --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC4626.sol @@ -0,0 +1,230 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC4626.sol) + +pragma solidity >=0.6.2; + +import {IERC20} from "../token/ERC20/IERC20.sol"; +import {IERC20Metadata} from "../token/ERC20/extensions/IERC20Metadata.sol"; + +/** + * @dev Interface of the ERC-4626 "Tokenized Vault Standard", as defined in + * https://eips.ethereum.org/EIPS/eip-4626[ERC-4626]. + */ +interface IERC4626 is IERC20, IERC20Metadata { + event Deposit(address indexed sender, address indexed owner, uint256 assets, uint256 shares); + + event Withdraw( + address indexed sender, + address indexed receiver, + address indexed owner, + uint256 assets, + uint256 shares + ); + + /** + * @dev Returns the address of the underlying token used for the Vault for accounting, depositing, and withdrawing. + * + * - MUST be an ERC-20 token contract. + * - MUST NOT revert. + */ + function asset() external view returns (address assetTokenAddress); + + /** + * @dev Returns the total amount of the underlying asset that is “managed” by Vault. + * + * - SHOULD include any compounding that occurs from yield. + * - MUST be inclusive of any fees that are charged against assets in the Vault. + * - MUST NOT revert. + */ + function totalAssets() external view returns (uint256 totalManagedAssets); + + /** + * @dev Returns the amount of shares that the Vault would exchange for the amount of assets provided, in an ideal + * scenario where all the conditions are met. + * + * - MUST NOT be inclusive of any fees that are charged against assets in the Vault. + * - MUST NOT show any variations depending on the caller. + * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange. + * - MUST NOT revert. + * + * NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the + * “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and + * from. + */ + function convertToShares(uint256 assets) external view returns (uint256 shares); + + /** + * @dev Returns the amount of assets that the Vault would exchange for the amount of shares provided, in an ideal + * scenario where all the conditions are met. + * + * - MUST NOT be inclusive of any fees that are charged against assets in the Vault. + * - MUST NOT show any variations depending on the caller. + * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange. + * - MUST NOT revert. + * + * NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the + * “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and + * from. + */ + function convertToAssets(uint256 shares) external view returns (uint256 assets); + + /** + * @dev Returns the maximum amount of the underlying asset that can be deposited into the Vault for the receiver, + * through a deposit call. + * + * - MUST return a limited value if receiver is subject to some deposit limit. + * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of assets that may be deposited. + * - MUST NOT revert. + */ + function maxDeposit(address receiver) external view returns (uint256 maxAssets); + + /** + * @dev Allows an on-chain or off-chain user to simulate the effects of their deposit at the current block, given + * current on-chain conditions. + * + * - MUST return as close to and no more than the exact amount of Vault shares that would be minted in a deposit + * call in the same transaction. I.e. deposit should return the same or more shares as previewDeposit if called + * in the same transaction. + * - MUST NOT account for deposit limits like those returned from maxDeposit and should always act as though the + * deposit would be accepted, regardless if the user has enough tokens approved, etc. + * - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees. + * - MUST NOT revert. + * + * NOTE: any unfavorable discrepancy between convertToShares and previewDeposit SHOULD be considered slippage in + * share price or some other type of condition, meaning the depositor will lose assets by depositing. + */ + function previewDeposit(uint256 assets) external view returns (uint256 shares); + + /** + * @dev Mints shares Vault shares to receiver by depositing exactly amount of underlying tokens. + * + * - MUST emit the Deposit event. + * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the + * deposit execution, and are accounted for during deposit. + * - MUST revert if all of assets cannot be deposited (due to deposit limit being reached, slippage, the user not + * approving enough underlying tokens to the Vault contract, etc). + * + * NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token. + */ + function deposit(uint256 assets, address receiver) external returns (uint256 shares); + + /** + * @dev Returns the maximum amount of the Vault shares that can be minted for the receiver, through a mint call. + * - MUST return a limited value if receiver is subject to some mint limit. + * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of shares that may be minted. + * - MUST NOT revert. + */ + function maxMint(address receiver) external view returns (uint256 maxShares); + + /** + * @dev Allows an on-chain or off-chain user to simulate the effects of their mint at the current block, given + * current on-chain conditions. + * + * - MUST return as close to and no fewer than the exact amount of assets that would be deposited in a mint call + * in the same transaction. I.e. mint should return the same or fewer assets as previewMint if called in the + * same transaction. + * - MUST NOT account for mint limits like those returned from maxMint and should always act as though the mint + * would be accepted, regardless if the user has enough tokens approved, etc. + * - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees. + * - MUST NOT revert. + * + * NOTE: any unfavorable discrepancy between convertToAssets and previewMint SHOULD be considered slippage in + * share price or some other type of condition, meaning the depositor will lose assets by minting. + */ + function previewMint(uint256 shares) external view returns (uint256 assets); + + /** + * @dev Mints exactly shares Vault shares to receiver by depositing amount of underlying tokens. + * + * - MUST emit the Deposit event. + * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the mint + * execution, and are accounted for during mint. + * - MUST revert if all of shares cannot be minted (due to deposit limit being reached, slippage, the user not + * approving enough underlying tokens to the Vault contract, etc). + * + * NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token. + */ + function mint(uint256 shares, address receiver) external returns (uint256 assets); + + /** + * @dev Returns the maximum amount of the underlying asset that can be withdrawn from the owner balance in the + * Vault, through a withdraw call. + * + * - MUST return a limited value if owner is subject to some withdrawal limit or timelock. + * - MUST NOT revert. + */ + function maxWithdraw(address owner) external view returns (uint256 maxAssets); + + /** + * @dev Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the current block, + * given current on-chain conditions. + * + * - MUST return as close to and no fewer than the exact amount of Vault shares that would be burned in a withdraw + * call in the same transaction. I.e. withdraw should return the same or fewer shares as previewWithdraw if + * called + * in the same transaction. + * - MUST NOT account for withdrawal limits like those returned from maxWithdraw and should always act as though + * the withdrawal would be accepted, regardless if the user has enough shares, etc. + * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees. + * - MUST NOT revert. + * + * NOTE: any unfavorable discrepancy between convertToShares and previewWithdraw SHOULD be considered slippage in + * share price or some other type of condition, meaning the depositor will lose assets by depositing. + */ + function previewWithdraw(uint256 assets) external view returns (uint256 shares); + + /** + * @dev Burns shares from owner and sends exactly assets of underlying tokens to receiver. + * + * - MUST emit the Withdraw event. + * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the + * withdraw execution, and are accounted for during withdraw. + * - MUST revert if all of assets cannot be withdrawn (due to withdrawal limit being reached, slippage, the owner + * not having enough shares, etc). + * + * Note that some implementations will require pre-requesting to the Vault before a withdrawal may be performed. + * Those methods should be performed separately. + */ + function withdraw(uint256 assets, address receiver, address owner) external returns (uint256 shares); + + /** + * @dev Returns the maximum amount of Vault shares that can be redeemed from the owner balance in the Vault, + * through a redeem call. + * + * - MUST return a limited value if owner is subject to some withdrawal limit or timelock. + * - MUST return balanceOf(owner) if owner is not subject to any withdrawal limit or timelock. + * - MUST NOT revert. + */ + function maxRedeem(address owner) external view returns (uint256 maxShares); + + /** + * @dev Allows an on-chain or off-chain user to simulate the effects of their redemption at the current block, + * given current on-chain conditions. + * + * - MUST return as close to and no more than the exact amount of assets that would be withdrawn in a redeem call + * in the same transaction. I.e. redeem should return the same or more assets as previewRedeem if called in the + * same transaction. + * - MUST NOT account for redemption limits like those returned from maxRedeem and should always act as though the + * redemption would be accepted, regardless if the user has enough shares, etc. + * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees. + * - MUST NOT revert. + * + * NOTE: any unfavorable discrepancy between convertToAssets and previewRedeem SHOULD be considered slippage in + * share price or some other type of condition, meaning the depositor will lose assets by redeeming. + */ + function previewRedeem(uint256 shares) external view returns (uint256 assets); + + /** + * @dev Burns exactly shares from owner and sends assets of underlying tokens to receiver. + * + * - MUST emit the Withdraw event. + * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the + * redeem execution, and are accounted for during redeem. + * - MUST revert if all of shares cannot be redeemed (due to withdrawal limit being reached, slippage, the owner + * not having enough shares, etc). + * + * NOTE: some implementations will require pre-requesting to the Vault before a withdrawal may be performed. + * Those methods should be performed separately. + */ + function redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets); +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC4906.sol b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC4906.sol new file mode 100644 index 00000000..09f13b21 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC4906.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC4906.sol) + +pragma solidity >=0.6.2; + +import {IERC165} from "./IERC165.sol"; +import {IERC721} from "./IERC721.sol"; + +/// @title ERC-721 Metadata Update Extension +interface IERC4906 is IERC165, IERC721 { + /// @dev This event emits when the metadata of a token is changed. + /// So that the third-party platforms such as NFT market could + /// timely update the images and related attributes of the NFT. + event MetadataUpdate(uint256 _tokenId); + + /// @dev This event emits when the metadata of a range of tokens is changed. + /// So that the third-party platforms such as NFT market could + /// timely update the images and related attributes of the NFTs. + event BatchMetadataUpdate(uint256 _fromTokenId, uint256 _toTokenId); +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC5267.sol b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC5267.sol new file mode 100644 index 00000000..96cd325b --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC5267.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC5267.sol) + +pragma solidity >=0.4.16; + +interface IERC5267 { + /** + * @dev MAY be emitted to signal that the domain could have changed. + */ + event EIP712DomainChanged(); + + /** + * @dev returns the fields and values that describe the domain separator used by this contract for EIP-712 + * signature. + */ + function eip712Domain() + external + view + returns ( + bytes1 fields, + string memory name, + string memory version, + uint256 chainId, + address verifyingContract, + bytes32 salt, + uint256[] memory extensions + ); +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC5313.sol b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC5313.sol new file mode 100644 index 00000000..9c946929 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC5313.sol @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC5313.sol) + +pragma solidity >=0.4.16; + +/** + * @dev Interface for the Light Contract Ownership Standard. + * + * A standardized minimal interface required to identify an account that controls a contract + */ +interface IERC5313 { + /** + * @dev Gets the address of the owner. + */ + function owner() external view returns (address); +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC5805.sol b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC5805.sol new file mode 100644 index 00000000..5d73abba --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC5805.sol @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC5805.sol) + +pragma solidity >=0.8.4; + +import {IVotes} from "../governance/utils/IVotes.sol"; +import {IERC6372} from "./IERC6372.sol"; + +interface IERC5805 is IERC6372, IVotes {} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC6372.sol b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC6372.sol new file mode 100644 index 00000000..447a8ea3 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC6372.sol @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC6372.sol) + +pragma solidity >=0.4.16; + +interface IERC6372 { + /** + * @dev Clock used for flagging checkpoints. Can be overridden to implement timestamp based checkpoints (and voting). + */ + function clock() external view returns (uint48); + + /** + * @dev Description of the clock + */ + // solhint-disable-next-line func-name-mixedcase + function CLOCK_MODE() external view returns (string memory); +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC721.sol b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC721.sol new file mode 100644 index 00000000..6ec51369 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC721.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC721.sol) + +pragma solidity >=0.6.2; + +import {IERC721} from "../token/ERC721/IERC721.sol"; diff --git a/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC721Enumerable.sol b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC721Enumerable.sol new file mode 100644 index 00000000..e713bc23 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC721Enumerable.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC721Enumerable.sol) + +pragma solidity >=0.6.2; + +import {IERC721Enumerable} from "../token/ERC721/extensions/IERC721Enumerable.sol"; diff --git a/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC721Metadata.sol b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC721Metadata.sol new file mode 100644 index 00000000..932afaaa --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC721Metadata.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC721Metadata.sol) + +pragma solidity >=0.6.2; + +import {IERC721Metadata} from "../token/ERC721/extensions/IERC721Metadata.sol"; diff --git a/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC721Receiver.sol b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC721Receiver.sol new file mode 100644 index 00000000..7b5fd47b --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC721Receiver.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC721Receiver.sol) + +pragma solidity >=0.5.0; + +import {IERC721Receiver} from "../token/ERC721/IERC721Receiver.sol"; diff --git a/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC777.sol b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC777.sol new file mode 100644 index 00000000..d65b9c7d --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC777.sol @@ -0,0 +1,200 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC777.sol) + +pragma solidity >=0.5.0; + +/** + * @dev Interface of the ERC-777 Token standard as defined in the ERC. + * + * This contract uses the + * https://eips.ethereum.org/EIPS/eip-1820[ERC-1820 registry standard] to let + * token holders and recipients react to token movements by using setting implementers + * for the associated interfaces in said registry. See {IERC1820Registry} and + * {IERC1820Implementer}. + */ +interface IERC777 { + /** + * @dev Emitted when `amount` tokens are created by `operator` and assigned to `to`. + * + * Note that some additional user `data` and `operatorData` can be logged in the event. + */ + event Minted(address indexed operator, address indexed to, uint256 amount, bytes data, bytes operatorData); + + /** + * @dev Emitted when `operator` destroys `amount` tokens from `account`. + * + * Note that some additional user `data` and `operatorData` can be logged in the event. + */ + event Burned(address indexed operator, address indexed from, uint256 amount, bytes data, bytes operatorData); + + /** + * @dev Emitted when `operator` is made operator for `tokenHolder`. + */ + event AuthorizedOperator(address indexed operator, address indexed tokenHolder); + + /** + * @dev Emitted when `operator` is revoked its operator status for `tokenHolder`. + */ + event RevokedOperator(address indexed operator, address indexed tokenHolder); + + /** + * @dev Returns the name of the token. + */ + function name() external view returns (string memory); + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() external view returns (string memory); + + /** + * @dev Returns the smallest part of the token that is not divisible. This + * means all token operations (creation, movement and destruction) must have + * amounts that are a multiple of this number. + * + * For most token contracts, this value will equal 1. + */ + function granularity() external view returns (uint256); + + /** + * @dev Returns the amount of tokens in existence. + */ + function totalSupply() external view returns (uint256); + + /** + * @dev Returns the amount of tokens owned by an account (`owner`). + */ + function balanceOf(address owner) external view returns (uint256); + + /** + * @dev Moves `amount` tokens from the caller's account to `recipient`. + * + * If send or receive hooks are registered for the caller and `recipient`, + * the corresponding functions will be called with `data` and empty + * `operatorData`. See {IERC777Sender} and {IERC777Recipient}. + * + * Emits a {Sent} event. + * + * Requirements + * + * - the caller must have at least `amount` tokens. + * - `recipient` cannot be the zero address. + * - if `recipient` is a contract, it must implement the {IERC777Recipient} + * interface. + */ + function send(address recipient, uint256 amount, bytes calldata data) external; + + /** + * @dev Destroys `amount` tokens from the caller's account, reducing the + * total supply. + * + * If a send hook is registered for the caller, the corresponding function + * will be called with `data` and empty `operatorData`. See {IERC777Sender}. + * + * Emits a {Burned} event. + * + * Requirements + * + * - the caller must have at least `amount` tokens. + */ + function burn(uint256 amount, bytes calldata data) external; + + /** + * @dev Returns true if an account is an operator of `tokenHolder`. + * Operators can send and burn tokens on behalf of their owners. All + * accounts are their own operator. + * + * See {operatorSend} and {operatorBurn}. + */ + function isOperatorFor(address operator, address tokenHolder) external view returns (bool); + + /** + * @dev Make an account an operator of the caller. + * + * See {isOperatorFor}. + * + * Emits an {AuthorizedOperator} event. + * + * Requirements + * + * - `operator` cannot be calling address. + */ + function authorizeOperator(address operator) external; + + /** + * @dev Revoke an account's operator status for the caller. + * + * See {isOperatorFor} and {defaultOperators}. + * + * Emits a {RevokedOperator} event. + * + * Requirements + * + * - `operator` cannot be calling address. + */ + function revokeOperator(address operator) external; + + /** + * @dev Returns the list of default operators. These accounts are operators + * for all token holders, even if {authorizeOperator} was never called on + * them. + * + * This list is immutable, but individual holders may revoke these via + * {revokeOperator}, in which case {isOperatorFor} will return false. + */ + function defaultOperators() external view returns (address[] memory); + + /** + * @dev Moves `amount` tokens from `sender` to `recipient`. The caller must + * be an operator of `sender`. + * + * If send or receive hooks are registered for `sender` and `recipient`, + * the corresponding functions will be called with `data` and + * `operatorData`. See {IERC777Sender} and {IERC777Recipient}. + * + * Emits a {Sent} event. + * + * Requirements + * + * - `sender` cannot be the zero address. + * - `sender` must have at least `amount` tokens. + * - the caller must be an operator for `sender`. + * - `recipient` cannot be the zero address. + * - if `recipient` is a contract, it must implement the {IERC777Recipient} + * interface. + */ + function operatorSend( + address sender, + address recipient, + uint256 amount, + bytes calldata data, + bytes calldata operatorData + ) external; + + /** + * @dev Destroys `amount` tokens from `account`, reducing the total supply. + * The caller must be an operator of `account`. + * + * If a send hook is registered for `account`, the corresponding function + * will be called with `data` and `operatorData`. See {IERC777Sender}. + * + * Emits a {Burned} event. + * + * Requirements + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + * - the caller must be an operator for `account`. + */ + function operatorBurn(address account, uint256 amount, bytes calldata data, bytes calldata operatorData) external; + + event Sent( + address indexed operator, + address indexed from, + address indexed to, + uint256 amount, + bytes data, + bytes operatorData + ); +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC777Recipient.sol b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC777Recipient.sol new file mode 100644 index 00000000..4277333c --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC777Recipient.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC777Recipient.sol) + +pragma solidity >=0.5.0; + +/** + * @dev Interface of the ERC-777 Tokens Recipient standard as defined in the ERC. + * + * Accounts can be notified of {IERC777} tokens being sent to them by having a + * contract implement this interface (contract holders can be their own + * implementer) and registering it on the + * https://eips.ethereum.org/EIPS/eip-1820[ERC-1820 global registry]. + * + * See {IERC1820Registry} and {IERC1820Implementer}. + */ +interface IERC777Recipient { + /** + * @dev Called by an {IERC777} token contract whenever tokens are being + * moved or created into a registered account (`to`). The type of operation + * is conveyed by `from` being the zero address or not. + * + * This call occurs _after_ the token contract's state is updated, so + * {IERC777-balanceOf}, etc., can be used to query the post-operation state. + * + * This function may revert to prevent the operation from being executed. + */ + function tokensReceived( + address operator, + address from, + address to, + uint256 amount, + bytes calldata userData, + bytes calldata operatorData + ) external; +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC777Sender.sol b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC777Sender.sol new file mode 100644 index 00000000..46d1b4a1 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC777Sender.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC777Sender.sol) + +pragma solidity >=0.5.0; + +/** + * @dev Interface of the ERC-777 Tokens Sender standard as defined in the ERC. + * + * {IERC777} Token holders can be notified of operations performed on their + * tokens by having a contract implement this interface (contract holders can be + * their own implementer) and registering it on the + * https://eips.ethereum.org/EIPS/eip-1820[ERC-1820 global registry]. + * + * See {IERC1820Registry} and {IERC1820Implementer}. + */ +interface IERC777Sender { + /** + * @dev Called by an {IERC777} token contract whenever a registered holder's + * (`from`) tokens are about to be moved or destroyed. The type of operation + * is conveyed by `to` being the zero address or not. + * + * This call occurs _before_ the token contract's state is updated, so + * {IERC777-balanceOf}, etc., can be used to query the pre-operation state. + * + * This function may revert to prevent the operation from being executed. + */ + function tokensToSend( + address operator, + address from, + address to, + uint256 amount, + bytes calldata userData, + bytes calldata operatorData + ) external; +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC7913.sol b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC7913.sol new file mode 100644 index 00000000..4f887fb9 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/IERC7913.sol @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC7913.sol) + +pragma solidity >=0.5.0; + +/** + * @dev Signature verifier interface. + */ +interface IERC7913SignatureVerifier { + /** + * @dev Verifies `signature` as a valid signature of `hash` by `key`. + * + * MUST return the bytes4 magic value IERC7913SignatureVerifier.verify.selector if the signature is valid. + * SHOULD return 0xffffffff or revert if the signature is not valid. + * SHOULD return 0xffffffff or revert if the key is empty + */ + function verify(bytes calldata key, bytes32 hash, bytes calldata signature) external view returns (bytes4); +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/interfaces/draft-IERC1822.sol b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/draft-IERC1822.sol new file mode 100644 index 00000000..2edb85de --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/draft-IERC1822.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/draft-IERC1822.sol) + +pragma solidity >=0.4.16; + +/** + * @dev ERC-1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified + * proxy whose upgrades are fully controlled by the current implementation. + */ +interface IERC1822Proxiable { + /** + * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation + * address. + * + * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks + * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this + * function revert if invoked through a proxy. + */ + function proxiableUUID() external view returns (bytes32); +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/interfaces/draft-IERC4337.sol b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/draft-IERC4337.sol new file mode 100644 index 00000000..752e4e43 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/draft-IERC4337.sol @@ -0,0 +1,253 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/draft-IERC4337.sol) + +pragma solidity >=0.8.4; + +/** + * @dev A https://github.com/ethereum/ercs/blob/master/ERCS/erc-4337.md#useroperation[user operation] is composed of the following elements: + * - `sender` (`address`): The account making the operation + * - `nonce` (`uint256`): Anti-replay parameter (see “Semi-abstracted Nonce Support” ) + * - `factory` (`address`): account factory, only for new accounts + * - `factoryData` (`bytes`): data for account factory (only if account factory exists) + * - `callData` (`bytes`): The data to pass to the sender during the main execution call + * - `callGasLimit` (`uint256`): The amount of gas to allocate the main execution call + * - `verificationGasLimit` (`uint256`): The amount of gas to allocate for the verification step + * - `preVerificationGas` (`uint256`): Extra gas to pay the bundler + * - `maxFeePerGas` (`uint256`): Maximum fee per gas (similar to EIP-1559 max_fee_per_gas) + * - `maxPriorityFeePerGas` (`uint256`): Maximum priority fee per gas (similar to EIP-1559 max_priority_fee_per_gas) + * - `paymaster` (`address`): Address of paymaster contract, (or empty, if account pays for itself) + * - `paymasterVerificationGasLimit` (`uint256`): The amount of gas to allocate for the paymaster validation code + * - `paymasterPostOpGasLimit` (`uint256`): The amount of gas to allocate for the paymaster post-operation code + * - `paymasterData` (`bytes`): Data for paymaster (only if paymaster exists) + * - `signature` (`bytes`): Data passed into the account to verify authorization + * + * When passed to on-chain contracts, the following packed version is used. + * - `sender` (`address`) + * - `nonce` (`uint256`) + * - `initCode` (`bytes`): concatenation of factory address and factoryData (or empty) + * - `callData` (`bytes`) + * - `accountGasLimits` (`bytes32`): concatenation of verificationGas (16 bytes) and callGas (16 bytes) + * - `preVerificationGas` (`uint256`) + * - `gasFees` (`bytes32`): concatenation of maxPriorityFeePerGas (16 bytes) and maxFeePerGas (16 bytes) + * - `paymasterAndData` (`bytes`): concatenation of paymaster fields (or empty) + * - `signature` (`bytes`) + */ +struct PackedUserOperation { + address sender; + uint256 nonce; + bytes initCode; // `abi.encodePacked(factory, factoryData)` + bytes callData; + bytes32 accountGasLimits; // `abi.encodePacked(verificationGasLimit, callGasLimit)` 16 bytes each + uint256 preVerificationGas; + bytes32 gasFees; // `abi.encodePacked(maxPriorityFeePerGas, maxFeePerGas)` 16 bytes each + bytes paymasterAndData; // `abi.encodePacked(paymaster, paymasterVerificationGasLimit, paymasterPostOpGasLimit, paymasterData)` (20 bytes, 16 bytes, 16 bytes, dynamic) + bytes signature; +} + +/** + * @dev Aggregates and validates multiple signatures for a batch of user operations. + * + * A contract could implement this interface with custom validation schemes that allow signature aggregation, + * enabling significant optimizations and gas savings for execution and transaction data cost. + * + * Bundlers and clients whitelist supported aggregators. + * + * See https://eips.ethereum.org/EIPS/eip-7766[ERC-7766] + */ +interface IAggregator { + /** + * @dev Validates the signature for a user operation. + * Returns an alternative signature that should be used during bundling. + */ + function validateUserOpSignature( + PackedUserOperation calldata userOp + ) external view returns (bytes memory sigForUserOp); + + /** + * @dev Returns an aggregated signature for a batch of user operation's signatures. + */ + function aggregateSignatures( + PackedUserOperation[] calldata userOps + ) external view returns (bytes memory aggregatesSignature); + + /** + * @dev Validates that the aggregated signature is valid for the user operations. + * + * Requirements: + * + * - The aggregated signature MUST match the given list of operations. + */ + function validateSignatures(PackedUserOperation[] calldata userOps, bytes calldata signature) external view; +} + +/** + * @dev Handle nonce management for accounts. + * + * Nonces are used in accounts as a replay protection mechanism and to ensure the order of user operations. + * To avoid limiting the number of operations an account can perform, the interface allows using parallel + * nonces by using a `key` parameter. + * + * See https://eips.ethereum.org/EIPS/eip-4337#semi-abstracted-nonce-support[ERC-4337 semi-abstracted nonce support]. + */ +interface IEntryPointNonces { + /** + * @dev Returns the nonce for a `sender` account and a `key`. + * + * Nonces for a certain `key` are always increasing. + */ + function getNonce(address sender, uint192 key) external view returns (uint256 nonce); +} + +/** + * @dev Handle stake management for entities (i.e. accounts, paymasters, factories). + * + * The EntryPoint must implement the following API to let entities like paymasters have a stake, + * and thus have more flexibility in their storage access + * (see https://eips.ethereum.org/EIPS/eip-4337#reputation-scoring-and-throttlingbanning-for-global-entities[reputation, throttling and banning.]) + */ +interface IEntryPointStake { + /** + * @dev Returns the balance of the account. + */ + function balanceOf(address account) external view returns (uint256); + + /** + * @dev Deposits `msg.value` to the account. + */ + function depositTo(address account) external payable; + + /** + * @dev Withdraws `withdrawAmount` from the account to `withdrawAddress`. + */ + function withdrawTo(address payable withdrawAddress, uint256 withdrawAmount) external; + + /** + * @dev Adds stake to the account with an unstake delay of `unstakeDelaySec`. + */ + function addStake(uint32 unstakeDelaySec) external payable; + + /** + * @dev Unlocks the stake of the account. + */ + function unlockStake() external; + + /** + * @dev Withdraws the stake of the account to `withdrawAddress`. + */ + function withdrawStake(address payable withdrawAddress) external; +} + +/** + * @dev Entry point for user operations. + * + * User operations are validated and executed by this contract. + */ +interface IEntryPoint is IEntryPointNonces, IEntryPointStake { + /** + * @dev A user operation at `opIndex` failed with `reason`. + */ + error FailedOp(uint256 opIndex, string reason); + + /** + * @dev A user operation at `opIndex` failed with `reason` and `inner` returned data. + */ + error FailedOpWithRevert(uint256 opIndex, string reason, bytes inner); + + /** + * @dev Batch of aggregated user operations per aggregator. + */ + struct UserOpsPerAggregator { + PackedUserOperation[] userOps; + IAggregator aggregator; + bytes signature; + } + + /** + * @dev Executes a batch of user operations. + * @param beneficiary Address to which gas is refunded upon completing the execution. + */ + function handleOps(PackedUserOperation[] calldata ops, address payable beneficiary) external; + + /** + * @dev Executes a batch of aggregated user operations per aggregator. + * @param beneficiary Address to which gas is refunded upon completing the execution. + */ + function handleAggregatedOps( + UserOpsPerAggregator[] calldata opsPerAggregator, + address payable beneficiary + ) external; +} + +/** + * @dev Base interface for an ERC-4337 account. + */ +interface IAccount { + /** + * @dev Validates a user operation. + * + * * MUST validate the caller is a trusted EntryPoint + * * MUST validate that the signature is a valid signature of the userOpHash, and SHOULD + * return SIG_VALIDATION_FAILED (and not revert) on signature mismatch. Any other error MUST revert. + * * MUST pay the entryPoint (caller) at least the “missingAccountFunds” (which might + * be zero, in case the current account’s deposit is high enough) + * + * Returns an encoded packed validation data that is composed of the following elements: + * + * - `authorizer` (`address`): 0 for success, 1 for failure, otherwise the address of an authorizer contract + * - `validUntil` (`uint48`): The UserOp is valid only up to this time. Zero for “infinite”. + * - `validAfter` (`uint48`): The UserOp is valid only after this time. + */ + function validateUserOp( + PackedUserOperation calldata userOp, + bytes32 userOpHash, + uint256 missingAccountFunds + ) external returns (uint256 validationData); +} + +/** + * @dev Support for executing user operations by prepending the {executeUserOp} function selector + * to the UserOperation's `callData`. + */ +interface IAccountExecute { + /** + * @dev Executes a user operation. + */ + function executeUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash) external; +} + +/** + * @dev Interface for a paymaster contract that agrees to pay for the gas costs of a user operation. + * + * NOTE: A paymaster must hold a stake to cover the required entrypoint stake and also the gas for the transaction. + */ +interface IPaymaster { + enum PostOpMode { + opSucceeded, + opReverted, + postOpReverted + } + + /** + * @dev Validates whether the paymaster is willing to pay for the user operation. See + * {IAccount-validateUserOp} for additional information on the return value. + * + * NOTE: Bundlers will reject this method if it modifies the state, unless it's whitelisted. + */ + function validatePaymasterUserOp( + PackedUserOperation calldata userOp, + bytes32 userOpHash, + uint256 maxCost + ) external returns (bytes memory context, uint256 validationData); + + /** + * @dev Verifies the sender is the entrypoint. + * @param actualGasCost the actual amount paid (by account or paymaster) for this UserOperation + * @param actualUserOpFeePerGas total gas used by this UserOperation (including preVerification, creation, validation and execution) + */ + function postOp( + PostOpMode mode, + bytes calldata context, + uint256 actualGasCost, + uint256 actualUserOpFeePerGas + ) external; +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/interfaces/draft-IERC6093.sol b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/draft-IERC6093.sol new file mode 100644 index 00000000..aef2b0a0 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/draft-IERC6093.sol @@ -0,0 +1,161 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/draft-IERC6093.sol) +pragma solidity >=0.8.4; + +/** + * @dev Standard ERC-20 Errors + * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-20 tokens. + */ +interface IERC20Errors { + /** + * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. + * @param sender Address whose tokens are being transferred. + * @param balance Current balance for the interacting account. + * @param needed Minimum amount required to perform a transfer. + */ + error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed); + + /** + * @dev Indicates a failure with the token `sender`. Used in transfers. + * @param sender Address whose tokens are being transferred. + */ + error ERC20InvalidSender(address sender); + + /** + * @dev Indicates a failure with the token `receiver`. Used in transfers. + * @param receiver Address to which tokens are being transferred. + */ + error ERC20InvalidReceiver(address receiver); + + /** + * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers. + * @param spender Address that may be allowed to operate on tokens without being their owner. + * @param allowance Amount of tokens a `spender` is allowed to operate with. + * @param needed Minimum amount required to perform a transfer. + */ + error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed); + + /** + * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. + * @param approver Address initiating an approval operation. + */ + error ERC20InvalidApprover(address approver); + + /** + * @dev Indicates a failure with the `spender` to be approved. Used in approvals. + * @param spender Address that may be allowed to operate on tokens without being their owner. + */ + error ERC20InvalidSpender(address spender); +} + +/** + * @dev Standard ERC-721 Errors + * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-721 tokens. + */ +interface IERC721Errors { + /** + * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in ERC-20. + * Used in balance queries. + * @param owner Address of the current owner of a token. + */ + error ERC721InvalidOwner(address owner); + + /** + * @dev Indicates a `tokenId` whose `owner` is the zero address. + * @param tokenId Identifier number of a token. + */ + error ERC721NonexistentToken(uint256 tokenId); + + /** + * @dev Indicates an error related to the ownership over a particular token. Used in transfers. + * @param sender Address whose tokens are being transferred. + * @param tokenId Identifier number of a token. + * @param owner Address of the current owner of a token. + */ + error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner); + + /** + * @dev Indicates a failure with the token `sender`. Used in transfers. + * @param sender Address whose tokens are being transferred. + */ + error ERC721InvalidSender(address sender); + + /** + * @dev Indicates a failure with the token `receiver`. Used in transfers. + * @param receiver Address to which tokens are being transferred. + */ + error ERC721InvalidReceiver(address receiver); + + /** + * @dev Indicates a failure with the `operator`’s approval. Used in transfers. + * @param operator Address that may be allowed to operate on tokens without being their owner. + * @param tokenId Identifier number of a token. + */ + error ERC721InsufficientApproval(address operator, uint256 tokenId); + + /** + * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. + * @param approver Address initiating an approval operation. + */ + error ERC721InvalidApprover(address approver); + + /** + * @dev Indicates a failure with the `operator` to be approved. Used in approvals. + * @param operator Address that may be allowed to operate on tokens without being their owner. + */ + error ERC721InvalidOperator(address operator); +} + +/** + * @dev Standard ERC-1155 Errors + * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-1155 tokens. + */ +interface IERC1155Errors { + /** + * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. + * @param sender Address whose tokens are being transferred. + * @param balance Current balance for the interacting account. + * @param needed Minimum amount required to perform a transfer. + * @param tokenId Identifier number of a token. + */ + error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId); + + /** + * @dev Indicates a failure with the token `sender`. Used in transfers. + * @param sender Address whose tokens are being transferred. + */ + error ERC1155InvalidSender(address sender); + + /** + * @dev Indicates a failure with the token `receiver`. Used in transfers. + * @param receiver Address to which tokens are being transferred. + */ + error ERC1155InvalidReceiver(address receiver); + + /** + * @dev Indicates a failure with the `operator`’s approval. Used in transfers. + * @param operator Address that may be allowed to operate on tokens without being their owner. + * @param owner Address of the current owner of a token. + */ + error ERC1155MissingApprovalForAll(address operator, address owner); + + /** + * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. + * @param approver Address initiating an approval operation. + */ + error ERC1155InvalidApprover(address approver); + + /** + * @dev Indicates a failure with the `operator` to be approved. Used in approvals. + * @param operator Address that may be allowed to operate on tokens without being their owner. + */ + error ERC1155InvalidOperator(address operator); + + /** + * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation. + * Used in batch transfers. + * @param idsLength Length of the array of token identifiers + * @param valuesLength Length of the array of token amounts + */ + error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength); +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/interfaces/draft-IERC6909.sol b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/draft-IERC6909.sol new file mode 100644 index 00000000..df157615 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/draft-IERC6909.sol @@ -0,0 +1,125 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/draft-IERC6909.sol) + +pragma solidity >=0.6.2; + +import {IERC165} from "../utils/introspection/IERC165.sol"; + +/** + * @dev Required interface of an ERC-6909 compliant contract, as defined in the + * https://eips.ethereum.org/EIPS/eip-6909[ERC]. + */ +interface IERC6909 is IERC165 { + /** + * @dev Emitted when the allowance of a `spender` for an `owner` is set for a token of type `id`. + * The new allowance is `amount`. + */ + event Approval(address indexed owner, address indexed spender, uint256 indexed id, uint256 amount); + + /** + * @dev Emitted when `owner` grants or revokes operator status for a `spender`. + */ + event OperatorSet(address indexed owner, address indexed spender, bool approved); + + /** + * @dev Emitted when `amount` tokens of type `id` are moved from `sender` to `receiver` initiated by `caller`. + */ + event Transfer( + address caller, + address indexed sender, + address indexed receiver, + uint256 indexed id, + uint256 amount + ); + + /** + * @dev Returns the amount of tokens of type `id` owned by `owner`. + */ + function balanceOf(address owner, uint256 id) external view returns (uint256); + + /** + * @dev Returns the amount of tokens of type `id` that `spender` is allowed to spend on behalf of `owner`. + * + * NOTE: Does not include operator allowances. + */ + function allowance(address owner, address spender, uint256 id) external view returns (uint256); + + /** + * @dev Returns true if `spender` is set as an operator for `owner`. + */ + function isOperator(address owner, address spender) external view returns (bool); + + /** + * @dev Sets an approval to `spender` for `amount` of tokens of type `id` from the caller's tokens. An `amount` of + * `type(uint256).max` signifies an unlimited approval. + * + * Must return true. + */ + function approve(address spender, uint256 id, uint256 amount) external returns (bool); + + /** + * @dev Grants or revokes unlimited transfer permission of any token id to `spender` for the caller's tokens. + * + * Must return true. + */ + function setOperator(address spender, bool approved) external returns (bool); + + /** + * @dev Transfers `amount` of token type `id` from the caller's account to `receiver`. + * + * Must return true. + */ + function transfer(address receiver, uint256 id, uint256 amount) external returns (bool); + + /** + * @dev Transfers `amount` of token type `id` from `sender` to `receiver`. + * + * Must return true. + */ + function transferFrom(address sender, address receiver, uint256 id, uint256 amount) external returns (bool); +} + +/** + * @dev Optional extension of {IERC6909} that adds metadata functions. + */ +interface IERC6909Metadata is IERC6909 { + /** + * @dev Returns the name of the token of type `id`. + */ + function name(uint256 id) external view returns (string memory); + + /** + * @dev Returns the ticker symbol of the token of type `id`. + */ + function symbol(uint256 id) external view returns (string memory); + + /** + * @dev Returns the number of decimals for the token of type `id`. + */ + function decimals(uint256 id) external view returns (uint8); +} + +/** + * @dev Optional extension of {IERC6909} that adds content URI functions. + */ +interface IERC6909ContentURI is IERC6909 { + /** + * @dev Returns URI for the contract. + */ + function contractURI() external view returns (string memory); + + /** + * @dev Returns the URI for the token of type `id`. + */ + function tokenURI(uint256 id) external view returns (string memory); +} + +/** + * @dev Optional extension of {IERC6909} that adds a token supply function. + */ +interface IERC6909TokenSupply is IERC6909 { + /** + * @dev Returns the total supply of the token of type `id`. + */ + function totalSupply(uint256 id) external view returns (uint256); +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/interfaces/draft-IERC7579.sol b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/draft-IERC7579.sol new file mode 100644 index 00000000..99a79c19 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/draft-IERC7579.sol @@ -0,0 +1,226 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/draft-IERC7579.sol) +pragma solidity >=0.8.4; + +import {PackedUserOperation} from "./draft-IERC4337.sol"; + +uint256 constant VALIDATION_SUCCESS = 0; +uint256 constant VALIDATION_FAILED = 1; +uint256 constant MODULE_TYPE_VALIDATOR = 1; +uint256 constant MODULE_TYPE_EXECUTOR = 2; +uint256 constant MODULE_TYPE_FALLBACK = 3; +uint256 constant MODULE_TYPE_HOOK = 4; + +/// @dev Minimal configuration interface for ERC-7579 modules +interface IERC7579Module { + /** + * @dev This function is called by the smart account during installation of the module + * @param data arbitrary data that may be passed to the module during `onInstall` initialization + * + * MUST revert on error (e.g. if module is already enabled) + */ + function onInstall(bytes calldata data) external; + + /** + * @dev This function is called by the smart account during uninstallation of the module + * @param data arbitrary data that may be passed to the module during `onUninstall` de-initialization + * + * MUST revert on error + */ + function onUninstall(bytes calldata data) external; + + /** + * @dev Returns boolean value if module is a certain type + * @param moduleTypeId the module type ID according the ERC-7579 spec + * + * MUST return true if the module is of the given type and false otherwise + */ + function isModuleType(uint256 moduleTypeId) external view returns (bool); +} + +/** + * @dev ERC-7579 Validation module (type 1). + * + * A module that implements logic to validate user operations and signatures. + */ +interface IERC7579Validator is IERC7579Module { + /** + * @dev Validates a UserOperation + * @param userOp the ERC-4337 PackedUserOperation + * @param userOpHash the hash of the ERC-4337 PackedUserOperation + * + * MUST validate that the signature is a valid signature of the userOpHash + * SHOULD return ERC-4337's SIG_VALIDATION_FAILED (and not revert) on signature mismatch + * See {IAccount-validateUserOp} for additional information on the return value + */ + function validateUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash) external returns (uint256); + + /** + * @dev Validates a signature using ERC-1271 + * @param sender the address that sent the ERC-1271 request to the smart account + * @param hash the hash of the ERC-1271 request + * @param signature the signature of the ERC-1271 request + * + * MUST return the ERC-1271 `MAGIC_VALUE` if the signature is valid + * MUST NOT modify state + */ + function isValidSignatureWithSender( + address sender, + bytes32 hash, + bytes calldata signature + ) external view returns (bytes4); +} + +/** + * @dev ERC-7579 Hooks module (type 4). + * + * A module that implements logic to execute before and after the account executes a user operation, + * either individually or batched. + */ +interface IERC7579Hook is IERC7579Module { + /** + * @dev Called by the smart account before execution + * @param msgSender the address that called the smart account + * @param value the value that was sent to the smart account + * @param msgData the data that was sent to the smart account + * + * MAY return arbitrary data in the `hookData` return value + */ + function preCheck( + address msgSender, + uint256 value, + bytes calldata msgData + ) external returns (bytes memory hookData); + + /** + * @dev Called by the smart account after execution + * @param hookData the data that was returned by the `preCheck` function + * + * MAY validate the `hookData` to validate transaction context of the `preCheck` function + */ + function postCheck(bytes calldata hookData) external; +} + +struct Execution { + address target; + uint256 value; + bytes callData; +} + +/** + * @dev ERC-7579 Execution. + * + * Accounts should implement this interface so that the Entrypoint and ERC-7579 modules can execute operations. + */ +interface IERC7579Execution { + /** + * @dev Executes a transaction on behalf of the account. + * @param mode The encoded execution mode of the transaction. See ModeLib.sol for details + * @param executionCalldata The encoded execution call data + * + * MUST ensure adequate authorization control: e.g. onlyEntryPointOrSelf if used with ERC-4337 + * If a mode is requested that is not supported by the Account, it MUST revert + */ + function execute(bytes32 mode, bytes calldata executionCalldata) external payable; + + /** + * @dev Executes a transaction on behalf of the account. + * This function is intended to be called by Executor Modules + * @param mode The encoded execution mode of the transaction. See ModeLib.sol for details + * @param executionCalldata The encoded execution call data + * @return returnData An array with the returned data of each executed subcall + * + * MUST ensure adequate authorization control: i.e. onlyExecutorModule + * If a mode is requested that is not supported by the Account, it MUST revert + */ + function executeFromExecutor( + bytes32 mode, + bytes calldata executionCalldata + ) external payable returns (bytes[] memory returnData); +} + +/** + * @dev ERC-7579 Account Config. + * + * Accounts should implement this interface to expose information that identifies the account, supported modules and capabilities. + */ +interface IERC7579AccountConfig { + /** + * @dev Returns the account id of the smart account + * @return accountImplementationId the account id of the smart account + * + * MUST return a non-empty string + * The accountId SHOULD be structured like so: + * "vendorname.accountname.semver" + * The id SHOULD be unique across all smart accounts + */ + function accountId() external view returns (string memory accountImplementationId); + + /** + * @dev Function to check if the account supports a certain execution mode (see above) + * @param encodedMode the encoded mode + * + * MUST return true if the account supports the mode and false otherwise + */ + function supportsExecutionMode(bytes32 encodedMode) external view returns (bool); + + /** + * @dev Function to check if the account supports a certain module typeId + * @param moduleTypeId the module type ID according to the ERC-7579 spec + * + * MUST return true if the account supports the module type and false otherwise + */ + function supportsModule(uint256 moduleTypeId) external view returns (bool); +} + +/** + * @dev ERC-7579 Module Config. + * + * Accounts should implement this interface to allow installing and uninstalling modules. + */ +interface IERC7579ModuleConfig { + event ModuleInstalled(uint256 moduleTypeId, address module); + event ModuleUninstalled(uint256 moduleTypeId, address module); + + /** + * @dev Installs a Module of a certain type on the smart account + * @param moduleTypeId the module type ID according to the ERC-7579 spec + * @param module the module address + * @param initData arbitrary data that may be passed to the module during `onInstall` + * initialization. + * + * MUST implement authorization control + * MUST call `onInstall` on the module with the `initData` parameter if provided + * MUST emit ModuleInstalled event + * MUST revert if the module is already installed or the initialization on the module failed + */ + function installModule(uint256 moduleTypeId, address module, bytes calldata initData) external; + + /** + * @dev Uninstalls a Module of a certain type on the smart account + * @param moduleTypeId the module type ID according the ERC-7579 spec + * @param module the module address + * @param deInitData arbitrary data that may be passed to the module during `onUninstall` + * deinitialization. + * + * MUST implement authorization control + * MUST call `onUninstall` on the module with the `deInitData` parameter if provided + * MUST emit ModuleUninstalled event + * MUST revert if the module is not installed or the deInitialization on the module failed + */ + function uninstallModule(uint256 moduleTypeId, address module, bytes calldata deInitData) external; + + /** + * @dev Returns whether a module is installed on the smart account + * @param moduleTypeId the module type ID according the ERC-7579 spec + * @param module the module address + * @param additionalContext arbitrary data that may be passed to determine if the module is installed + * + * MUST return true if the module is installed and false otherwise + */ + function isModuleInstalled( + uint256 moduleTypeId, + address module, + bytes calldata additionalContext + ) external view returns (bool); +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/interfaces/draft-IERC7674.sol b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/draft-IERC7674.sol new file mode 100644 index 00000000..240c0e9a --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/draft-IERC7674.sol @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/draft-IERC7674.sol) + +pragma solidity >=0.6.2; + +import {IERC20} from "./IERC20.sol"; + +/** + * @dev Temporary Approval Extension for ERC-20 (https://github.com/ethereum/ERCs/pull/358[ERC-7674]) + */ +interface IERC7674 is IERC20 { + /** + * @dev Set the temporary allowance, allowing `spender` to withdraw (within the same transaction) assets + * held by the caller. + */ + function temporaryApprove(address spender, uint256 value) external returns (bool success); +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/interfaces/draft-IERC7802.sol b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/draft-IERC7802.sol new file mode 100644 index 00000000..940edddb --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/draft-IERC7802.sol @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/draft-IERC7802.sol) +pragma solidity >=0.6.2; + +import {IERC165} from "./IERC165.sol"; + +/// @title IERC7802 +/// @notice Defines the interface for crosschain ERC20 transfers. +interface IERC7802 is IERC165 { + /// @notice Emitted when a crosschain transfer mints tokens. + /// @param to Address of the account tokens are being minted for. + /// @param amount Amount of tokens minted. + /// @param sender Address of the caller (msg.sender) who invoked crosschainMint. + event CrosschainMint(address indexed to, uint256 amount, address indexed sender); + + /// @notice Emitted when a crosschain transfer burns tokens. + /// @param from Address of the account tokens are being burned from. + /// @param amount Amount of tokens burned. + /// @param sender Address of the caller (msg.sender) who invoked crosschainBurn. + event CrosschainBurn(address indexed from, uint256 amount, address indexed sender); + + /// @notice Mint tokens through a crosschain transfer. + /// @param _to Address to mint tokens to. + /// @param _amount Amount of tokens to mint. + function crosschainMint(address _to, uint256 _amount) external; + + /// @notice Burn tokens through a crosschain transfer. + /// @param _from Address to burn tokens from. + /// @param _amount Amount of tokens to burn. + function crosschainBurn(address _from, uint256 _amount) external; +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/interfaces/draft-IERC7821.sol b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/draft-IERC7821.sol new file mode 100644 index 00000000..8a11a6ee --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/interfaces/draft-IERC7821.sol @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/draft-IERC7821.sol) + +pragma solidity >=0.5.0; + +/** + * @dev Interface for minimal batch executor. + */ +interface IERC7821 { + /** + * @dev Executes the calls in `executionData`. + * Reverts and bubbles up error if any call fails. + * + * `executionData` encoding: + * - If `opData` is empty, `executionData` is simply `abi.encode(calls)`. + * - Else, `executionData` is `abi.encode(calls, opData)`. + * See: https://eips.ethereum.org/EIPS/eip-7579 + * + * Supported modes: + * - `bytes32(0x01000000000000000000...)`: does not support optional `opData`. + * - `bytes32(0x01000000000078210001...)`: supports optional `opData`. + * + * Authorization checks: + * - If `opData` is empty, the implementation SHOULD require that + * `msg.sender == address(this)`. + * - If `opData` is not empty, the implementation SHOULD use the signature + * encoded in `opData` to determine if the caller can perform the execution. + * + * `opData` may be used to store additional data for authentication, + * paymaster data, gas limits, etc. + * + * For calldata compression efficiency, if a Call.to is `address(0)`, + * it will be replaced with `address(this)`. + */ + function execute(bytes32 mode, bytes calldata executionData) external payable; + + /** + * @dev This function is provided for frontends to detect support. + * Only returns true for: + * - `bytes32(0x01000000000000000000...)`: does not support optional `opData`. + * - `bytes32(0x01000000000078210001...)`: supports optional `opData`. + */ + function supportsExecutionMode(bytes32 mode) external view returns (bool); +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/metatx/ERC2771Context.sol b/dependencies/@openzeppelin-contracts-5.4.0/metatx/ERC2771Context.sol new file mode 100644 index 00000000..cdff6f74 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/metatx/ERC2771Context.sol @@ -0,0 +1,90 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (metatx/ERC2771Context.sol) + +pragma solidity ^0.8.20; + +import {Context} from "../utils/Context.sol"; + +/** + * @dev Context variant with ERC-2771 support. + * + * WARNING: Avoid using this pattern in contracts that rely in a specific calldata length as they'll + * be affected by any forwarder whose `msg.data` is suffixed with the `from` address according to the ERC-2771 + * specification adding the address size in bytes (20) to the calldata size. An example of an unexpected + * behavior could be an unintended fallback (or another function) invocation while trying to invoke the `receive` + * function only accessible if `msg.data.length == 0`. + * + * WARNING: The usage of `delegatecall` in this contract is dangerous and may result in context corruption. + * Any forwarded request to this contract triggering a `delegatecall` to itself will result in an invalid {_msgSender} + * recovery. + */ +abstract contract ERC2771Context is Context { + /// @custom:oz-upgrades-unsafe-allow state-variable-immutable + address private immutable _trustedForwarder; + + /** + * @dev Initializes the contract with a trusted forwarder, which will be able to + * invoke functions on this contract on behalf of other accounts. + * + * NOTE: The trusted forwarder can be replaced by overriding {trustedForwarder}. + */ + /// @custom:oz-upgrades-unsafe-allow constructor + constructor(address trustedForwarder_) { + _trustedForwarder = trustedForwarder_; + } + + /** + * @dev Returns the address of the trusted forwarder. + */ + function trustedForwarder() public view virtual returns (address) { + return _trustedForwarder; + } + + /** + * @dev Indicates whether any particular address is the trusted forwarder. + */ + function isTrustedForwarder(address forwarder) public view virtual returns (bool) { + return forwarder == trustedForwarder(); + } + + /** + * @dev Override for `msg.sender`. Defaults to the original `msg.sender` whenever + * a call is not performed by the trusted forwarder or the calldata length is less than + * 20 bytes (an address length). + */ + function _msgSender() internal view virtual override returns (address) { + uint256 calldataLength = msg.data.length; + uint256 contextSuffixLength = _contextSuffixLength(); + if (calldataLength >= contextSuffixLength && isTrustedForwarder(msg.sender)) { + unchecked { + return address(bytes20(msg.data[calldataLength - contextSuffixLength:])); + } + } else { + return super._msgSender(); + } + } + + /** + * @dev Override for `msg.data`. Defaults to the original `msg.data` whenever + * a call is not performed by the trusted forwarder or the calldata length is less than + * 20 bytes (an address length). + */ + function _msgData() internal view virtual override returns (bytes calldata) { + uint256 calldataLength = msg.data.length; + uint256 contextSuffixLength = _contextSuffixLength(); + if (calldataLength >= contextSuffixLength && isTrustedForwarder(msg.sender)) { + unchecked { + return msg.data[:calldataLength - contextSuffixLength]; + } + } else { + return super._msgData(); + } + } + + /** + * @dev ERC-2771 specifies the context as being a single address (20 bytes). + */ + function _contextSuffixLength() internal view virtual override returns (uint256) { + return 20; + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/metatx/ERC2771Forwarder.sol b/dependencies/@openzeppelin-contracts-5.4.0/metatx/ERC2771Forwarder.sol new file mode 100644 index 00000000..a463e70e --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/metatx/ERC2771Forwarder.sol @@ -0,0 +1,372 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.3.0) (metatx/ERC2771Forwarder.sol) + +pragma solidity ^0.8.20; + +import {ERC2771Context} from "./ERC2771Context.sol"; +import {ECDSA} from "../utils/cryptography/ECDSA.sol"; +import {EIP712} from "../utils/cryptography/EIP712.sol"; +import {Nonces} from "../utils/Nonces.sol"; +import {Address} from "../utils/Address.sol"; +import {Errors} from "../utils/Errors.sol"; + +/** + * @dev A forwarder compatible with ERC-2771 contracts. See {ERC2771Context}. + * + * This forwarder operates on forward requests that include: + * + * * `from`: An address to operate on behalf of. It is required to be equal to the request signer. + * * `to`: The address that should be called. + * * `value`: The amount of native token to attach with the requested call. + * * `gas`: The amount of gas limit that will be forwarded with the requested call. + * * `nonce`: A unique transaction ordering identifier to avoid replayability and request invalidation. + * * `deadline`: A timestamp after which the request is not executable anymore. + * * `data`: Encoded `msg.data` to send with the requested call. + * + * Relayers are able to submit batches if they are processing a high volume of requests. With high + * throughput, relayers may run into limitations of the chain such as limits on the number of + * transactions in the mempool. In these cases the recommendation is to distribute the load among + * multiple accounts. + * + * NOTE: Batching requests includes an optional refund for unused `msg.value` that is achieved by + * performing a call with empty calldata. While this is within the bounds of ERC-2771 compliance, + * if the refund receiver happens to consider the forwarder a trusted forwarder, it MUST properly + * handle `msg.data.length == 0`. `ERC2771Context` in OpenZeppelin Contracts versions prior to 4.9.3 + * do not handle this properly. + * + * ==== Security Considerations + * + * If a relayer submits a forward request, it should be willing to pay up to 100% of the gas amount + * specified in the request. This contract does not implement any kind of retribution for this gas, + * and it is assumed that there is an out of band incentive for relayers to pay for execution on + * behalf of signers. Often, the relayer is operated by a project that will consider it a user + * acquisition cost. + * + * By offering to pay for gas, relayers are at risk of having that gas used by an attacker toward + * some other purpose that is not aligned with the expected out of band incentives. If you operate a + * relayer, consider whitelisting target contracts and function selectors. When relaying ERC-721 or + * ERC-1155 transfers specifically, consider rejecting the use of the `data` field, since it can be + * used to execute arbitrary code. + */ +contract ERC2771Forwarder is EIP712, Nonces { + using ECDSA for bytes32; + + struct ForwardRequestData { + address from; + address to; + uint256 value; + uint256 gas; + uint48 deadline; + bytes data; + bytes signature; + } + + bytes32 internal constant _FORWARD_REQUEST_TYPEHASH = + keccak256( + "ForwardRequest(address from,address to,uint256 value,uint256 gas,uint256 nonce,uint48 deadline,bytes data)" + ); + + /** + * @dev Emitted when a `ForwardRequest` is executed. + * + * NOTE: An unsuccessful forward request could be due to an invalid signature, an expired deadline, + * or simply a revert in the requested call. The contract guarantees that the relayer is not able to force + * the requested call to run out of gas. + */ + event ExecutedForwardRequest(address indexed signer, uint256 nonce, bool success); + + /** + * @dev The request `from` doesn't match with the recovered `signer`. + */ + error ERC2771ForwarderInvalidSigner(address signer, address from); + + /** + * @dev The `requestedValue` doesn't match with the available `msgValue`. + */ + error ERC2771ForwarderMismatchedValue(uint256 requestedValue, uint256 msgValue); + + /** + * @dev The request `deadline` has expired. + */ + error ERC2771ForwarderExpiredRequest(uint48 deadline); + + /** + * @dev The request target doesn't trust the `forwarder`. + */ + error ERC2771UntrustfulTarget(address target, address forwarder); + + /** + * @dev See {EIP712-constructor}. + */ + constructor(string memory name) EIP712(name, "1") {} + + /** + * @dev Returns `true` if a request is valid for a provided `signature` at the current block timestamp. + * + * A transaction is considered valid when the target trusts this forwarder, the request hasn't expired + * (deadline is not met), and the signer matches the `from` parameter of the signed request. + * + * NOTE: A request may return false here but it won't cause {executeBatch} to revert if a refund + * receiver is provided. + */ + function verify(ForwardRequestData calldata request) public view virtual returns (bool) { + (bool isTrustedForwarder, bool active, bool signerMatch, ) = _validate(request); + return isTrustedForwarder && active && signerMatch; + } + + /** + * @dev Executes a `request` on behalf of `signature`'s signer using the ERC-2771 protocol. The gas + * provided to the requested call may not be exactly the amount requested, but the call will not run + * out of gas. Will revert if the request is invalid or the call reverts, in this case the nonce is not consumed. + * + * Requirements: + * + * - The request value should be equal to the provided `msg.value`. + * - The request should be valid according to {verify}. + */ + function execute(ForwardRequestData calldata request) public payable virtual { + // We make sure that msg.value and request.value match exactly. + // If the request is invalid or the call reverts, this whole function + // will revert, ensuring value isn't stuck. + if (msg.value != request.value) { + revert ERC2771ForwarderMismatchedValue(request.value, msg.value); + } + + if (!_execute(request, true)) { + revert Errors.FailedCall(); + } + } + + /** + * @dev Batch version of {execute} with optional refunding and atomic execution. + * + * In case a batch contains at least one invalid request (see {verify}), the + * request will be skipped and the `refundReceiver` parameter will receive back the + * unused requested value at the end of the execution. This is done to prevent reverting + * the entire batch when a request is invalid or has already been submitted. + * + * If the `refundReceiver` is the `address(0)`, this function will revert when at least + * one of the requests was not valid instead of skipping it. This could be useful if + * a batch is required to get executed atomically (at least at the top-level). For example, + * refunding (and thus atomicity) can be opt-out if the relayer is using a service that avoids + * including reverted transactions. + * + * Requirements: + * + * - The sum of the requests' values should be equal to the provided `msg.value`. + * - All of the requests should be valid (see {verify}) when `refundReceiver` is the zero address. + * + * NOTE: Setting a zero `refundReceiver` guarantees an all-or-nothing requests execution only for + * the first-level forwarded calls. In case a forwarded request calls to a contract with another + * subcall, the second-level call may revert without the top-level call reverting. + */ + function executeBatch( + ForwardRequestData[] calldata requests, + address payable refundReceiver + ) public payable virtual { + bool atomic = refundReceiver == address(0); + + uint256 requestsValue; + uint256 refundValue; + + for (uint256 i; i < requests.length; ++i) { + requestsValue += requests[i].value; + bool success = _execute(requests[i], atomic); + if (!success) { + refundValue += requests[i].value; + } + } + + // The batch should revert if there's a mismatched msg.value provided + // to avoid request value tampering + if (requestsValue != msg.value) { + revert ERC2771ForwarderMismatchedValue(requestsValue, msg.value); + } + + // Some requests with value were invalid (possibly due to frontrunning). + // To avoid leaving ETH in the contract this value is refunded. + if (refundValue != 0) { + // We know refundReceiver != address(0) && requestsValue == msg.value + // meaning we can ensure refundValue is not taken from the original contract's balance + // and refundReceiver is a known account. + Address.sendValue(refundReceiver, refundValue); + } + } + + /** + * @dev Validates if the provided request can be executed at current block timestamp with + * the given `request.signature` on behalf of `request.signer`. + */ + function _validate( + ForwardRequestData calldata request + ) internal view virtual returns (bool isTrustedForwarder, bool active, bool signerMatch, address signer) { + (bool isValid, address recovered) = _recoverForwardRequestSigner(request); + + return ( + _isTrustedByTarget(request.to), + request.deadline >= block.timestamp, + isValid && recovered == request.from, + recovered + ); + } + + /** + * @dev Returns a tuple with the recovered the signer of an EIP712 forward request message hash + * and a boolean indicating if the signature is valid. + * + * NOTE: The signature is considered valid if {ECDSA-tryRecover} indicates no recover error for it. + */ + function _recoverForwardRequestSigner( + ForwardRequestData calldata request + ) internal view virtual returns (bool isValid, address signer) { + (address recovered, ECDSA.RecoverError err, ) = _hashTypedDataV4( + keccak256( + abi.encode( + _FORWARD_REQUEST_TYPEHASH, + request.from, + request.to, + request.value, + request.gas, + nonces(request.from), + request.deadline, + keccak256(request.data) + ) + ) + ).tryRecover(request.signature); + + return (err == ECDSA.RecoverError.NoError, recovered); + } + + /** + * @dev Validates and executes a signed request returning the request call `success` value. + * + * Internal function without msg.value validation. + * + * Requirements: + * + * - The caller must have provided enough gas to forward with the call. + * - The request must be valid (see {verify}) if the `requireValidRequest` is true. + * + * Emits an {ExecutedForwardRequest} event. + * + * IMPORTANT: Using this function doesn't check that all the `msg.value` was sent, potentially + * leaving value stuck in the contract. + */ + function _execute( + ForwardRequestData calldata request, + bool requireValidRequest + ) internal virtual returns (bool success) { + (bool isTrustedForwarder, bool active, bool signerMatch, address signer) = _validate(request); + + // Need to explicitly specify if a revert is required since non-reverting is default for + // batches and reversion is opt-in since it could be useful in some scenarios + if (requireValidRequest) { + if (!isTrustedForwarder) { + revert ERC2771UntrustfulTarget(request.to, address(this)); + } + + if (!active) { + revert ERC2771ForwarderExpiredRequest(request.deadline); + } + + if (!signerMatch) { + revert ERC2771ForwarderInvalidSigner(signer, request.from); + } + } + + // Ignore an invalid request because requireValidRequest = false + if (isTrustedForwarder && signerMatch && active) { + // Nonce should be used before the call to prevent reusing by reentrancy + uint256 currentNonce = _useNonce(signer); + + uint256 reqGas = request.gas; + address to = request.to; + uint256 value = request.value; + bytes memory data = abi.encodePacked(request.data, request.from); + + uint256 gasLeft; + + assembly ("memory-safe") { + success := call(reqGas, to, value, add(data, 0x20), mload(data), 0, 0) + gasLeft := gas() + } + + _checkForwardedGas(gasLeft, request); + + emit ExecutedForwardRequest(signer, currentNonce, success); + } + } + + /** + * @dev Returns whether the target trusts this forwarder. + * + * This function performs a static call to the target contract calling the + * {ERC2771Context-isTrustedForwarder} function. + * + * NOTE: Consider the execution of this forwarder is permissionless. Without this check, anyone may transfer assets + * that are owned by, or are approved to this forwarder. + */ + function _isTrustedByTarget(address target) internal view virtual returns (bool) { + bytes memory encodedParams = abi.encodeCall(ERC2771Context.isTrustedForwarder, (address(this))); + + bool success; + uint256 returnSize; + uint256 returnValue; + assembly ("memory-safe") { + // Perform the staticcall and save the result in the scratch space. + // | Location | Content | Content (Hex) | + // |-----------|----------|--------------------------------------------------------------------| + // | | | result ↓ | + // | 0x00:0x1F | selector | 0x0000000000000000000000000000000000000000000000000000000000000001 | + success := staticcall(gas(), target, add(encodedParams, 0x20), mload(encodedParams), 0, 0x20) + returnSize := returndatasize() + returnValue := mload(0) + } + + return success && returnSize >= 0x20 && returnValue > 0; + } + + /** + * @dev Checks if the requested gas was correctly forwarded to the callee. + * + * As a consequence of https://eips.ethereum.org/EIPS/eip-150[EIP-150]: + * - At most `gasleft() - floor(gasleft() / 64)` is forwarded to the callee. + * - At least `floor(gasleft() / 64)` is kept in the caller. + * + * It reverts consuming all the available gas if the forwarded gas is not the requested gas. + * + * IMPORTANT: The `gasLeft` parameter should be measured exactly at the end of the forwarded call. + * Any gas consumed in between will make room for bypassing this check. + */ + function _checkForwardedGas(uint256 gasLeft, ForwardRequestData calldata request) private pure { + // To avoid insufficient gas griefing attacks, as referenced in https://ronan.eth.limo/blog/ethereum-gas-dangers/ + // + // A malicious relayer can attempt to shrink the gas forwarded so that the underlying call reverts out-of-gas + // but the forwarding itself still succeeds. In order to make sure that the subcall received sufficient gas, + // we will inspect gasleft() after the forwarding. + // + // Let X be the gas available before the subcall, such that the subcall gets at most X * 63 / 64. + // We can't know X after CALL dynamic costs, but we want it to be such that X * 63 / 64 >= req.gas. + // Let Y be the gas used in the subcall. gasleft() measured immediately after the subcall will be gasleft() = X - Y. + // If the subcall ran out of gas, then Y = X * 63 / 64 and gasleft() = X - Y = X / 64. + // Under this assumption req.gas / 63 > gasleft() is true if and only if + // req.gas / 63 > X / 64, or equivalently req.gas > X * 63 / 64. + // This means that if the subcall runs out of gas we are able to detect that insufficient gas was passed. + // + // We will now also see that req.gas / 63 > gasleft() implies that req.gas >= X * 63 / 64. + // The contract guarantees Y <= req.gas, thus gasleft() = X - Y >= X - req.gas. + // - req.gas / 63 > gasleft() + // - req.gas / 63 >= X - req.gas + // - req.gas >= X * 63 / 64 + // In other words if req.gas < X * 63 / 64 then req.gas / 63 <= gasleft(), thus if the relayer behaves honestly + // the forwarding does not revert. + if (gasLeft < request.gas / 63) { + // We explicitly trigger invalid opcode to consume all gas and bubble-up the effects, since + // neither revert or assert consume all gas since Solidity 0.8.20 + // https://docs.soliditylang.org/en/v0.8.20/control-structures.html#panic-via-assert-and-error-via-require + assembly ("memory-safe") { + invalid() + } + } + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/proxy/Clones.sol b/dependencies/@openzeppelin-contracts-5.4.0/proxy/Clones.sol new file mode 100644 index 00000000..1eb71b73 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/proxy/Clones.sol @@ -0,0 +1,294 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (proxy/Clones.sol) + +pragma solidity ^0.8.20; + +import {Create2} from "../utils/Create2.sol"; +import {Errors} from "../utils/Errors.sol"; + +/** + * @dev https://eips.ethereum.org/EIPS/eip-1167[ERC-1167] is a standard for + * deploying minimal proxy contracts, also known as "clones". + * + * > To simply and cheaply clone contract functionality in an immutable way, this standard specifies + * > a minimal bytecode implementation that delegates all calls to a known, fixed address. + * + * The library includes functions to deploy a proxy using either `create` (traditional deployment) or `create2` + * (salted deterministic deployment). It also includes functions to predict the addresses of clones deployed using the + * deterministic method. + */ +library Clones { + error CloneArgumentsTooLong(); + + /** + * @dev Deploys and returns the address of a clone that mimics the behavior of `implementation`. + * + * This function uses the create opcode, which should never revert. + * + * WARNING: This function does not check if `implementation` has code. A clone that points to an address + * without code cannot be initialized. Initialization calls may appear to be successful when, in reality, they + * have no effect and leave the clone uninitialized, allowing a third party to initialize it later. + */ + function clone(address implementation) internal returns (address instance) { + return clone(implementation, 0); + } + + /** + * @dev Same as {xref-Clones-clone-address-}[clone], but with a `value` parameter to send native currency + * to the new contract. + * + * WARNING: This function does not check if `implementation` has code. A clone that points to an address + * without code cannot be initialized. Initialization calls may appear to be successful when, in reality, they + * have no effect and leave the clone uninitialized, allowing a third party to initialize it later. + * + * NOTE: Using a non-zero value at creation will require the contract using this function (e.g. a factory) + * to always have enough balance for new deployments. Consider exposing this function under a payable method. + */ + function clone(address implementation, uint256 value) internal returns (address instance) { + if (address(this).balance < value) { + revert Errors.InsufficientBalance(address(this).balance, value); + } + assembly ("memory-safe") { + // Cleans the upper 96 bits of the `implementation` word, then packs the first 3 bytes + // of the `implementation` address with the bytecode before the address. + mstore(0x00, or(shr(0xe8, shl(0x60, implementation)), 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000)) + // Packs the remaining 17 bytes of `implementation` with the bytecode after the address. + mstore(0x20, or(shl(0x78, implementation), 0x5af43d82803e903d91602b57fd5bf3)) + instance := create(value, 0x09, 0x37) + } + if (instance == address(0)) { + revert Errors.FailedDeployment(); + } + } + + /** + * @dev Deploys and returns the address of a clone that mimics the behavior of `implementation`. + * + * This function uses the create2 opcode and a `salt` to deterministically deploy + * the clone. Using the same `implementation` and `salt` multiple times will revert, since + * the clones cannot be deployed twice at the same address. + * + * WARNING: This function does not check if `implementation` has code. A clone that points to an address + * without code cannot be initialized. Initialization calls may appear to be successful when, in reality, they + * have no effect and leave the clone uninitialized, allowing a third party to initialize it later. + */ + function cloneDeterministic(address implementation, bytes32 salt) internal returns (address instance) { + return cloneDeterministic(implementation, salt, 0); + } + + /** + * @dev Same as {xref-Clones-cloneDeterministic-address-bytes32-}[cloneDeterministic], but with + * a `value` parameter to send native currency to the new contract. + * + * WARNING: This function does not check if `implementation` has code. A clone that points to an address + * without code cannot be initialized. Initialization calls may appear to be successful when, in reality, they + * have no effect and leave the clone uninitialized, allowing a third party to initialize it later. + * + * NOTE: Using a non-zero value at creation will require the contract using this function (e.g. a factory) + * to always have enough balance for new deployments. Consider exposing this function under a payable method. + */ + function cloneDeterministic( + address implementation, + bytes32 salt, + uint256 value + ) internal returns (address instance) { + if (address(this).balance < value) { + revert Errors.InsufficientBalance(address(this).balance, value); + } + assembly ("memory-safe") { + // Cleans the upper 96 bits of the `implementation` word, then packs the first 3 bytes + // of the `implementation` address with the bytecode before the address. + mstore(0x00, or(shr(0xe8, shl(0x60, implementation)), 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000)) + // Packs the remaining 17 bytes of `implementation` with the bytecode after the address. + mstore(0x20, or(shl(0x78, implementation), 0x5af43d82803e903d91602b57fd5bf3)) + instance := create2(value, 0x09, 0x37, salt) + } + if (instance == address(0)) { + revert Errors.FailedDeployment(); + } + } + + /** + * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}. + */ + function predictDeterministicAddress( + address implementation, + bytes32 salt, + address deployer + ) internal pure returns (address predicted) { + assembly ("memory-safe") { + let ptr := mload(0x40) + mstore(add(ptr, 0x38), deployer) + mstore(add(ptr, 0x24), 0x5af43d82803e903d91602b57fd5bf3ff) + mstore(add(ptr, 0x14), implementation) + mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73) + mstore(add(ptr, 0x58), salt) + mstore(add(ptr, 0x78), keccak256(add(ptr, 0x0c), 0x37)) + predicted := and(keccak256(add(ptr, 0x43), 0x55), 0xffffffffffffffffffffffffffffffffffffffff) + } + } + + /** + * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}. + */ + function predictDeterministicAddress( + address implementation, + bytes32 salt + ) internal view returns (address predicted) { + return predictDeterministicAddress(implementation, salt, address(this)); + } + + /** + * @dev Deploys and returns the address of a clone that mimics the behavior of `implementation` with custom + * immutable arguments. These are provided through `args` and cannot be changed after deployment. To + * access the arguments within the implementation, use {fetchCloneArgs}. + * + * This function uses the create opcode, which should never revert. + * + * WARNING: This function does not check if `implementation` has code. A clone that points to an address + * without code cannot be initialized. Initialization calls may appear to be successful when, in reality, they + * have no effect and leave the clone uninitialized, allowing a third party to initialize it later. + */ + function cloneWithImmutableArgs(address implementation, bytes memory args) internal returns (address instance) { + return cloneWithImmutableArgs(implementation, args, 0); + } + + /** + * @dev Same as {xref-Clones-cloneWithImmutableArgs-address-bytes-}[cloneWithImmutableArgs], but with a `value` + * parameter to send native currency to the new contract. + * + * WARNING: This function does not check if `implementation` has code. A clone that points to an address + * without code cannot be initialized. Initialization calls may appear to be successful when, in reality, they + * have no effect and leave the clone uninitialized, allowing a third party to initialize it later. + * + * NOTE: Using a non-zero value at creation will require the contract using this function (e.g. a factory) + * to always have enough balance for new deployments. Consider exposing this function under a payable method. + */ + function cloneWithImmutableArgs( + address implementation, + bytes memory args, + uint256 value + ) internal returns (address instance) { + if (address(this).balance < value) { + revert Errors.InsufficientBalance(address(this).balance, value); + } + bytes memory bytecode = _cloneCodeWithImmutableArgs(implementation, args); + assembly ("memory-safe") { + instance := create(value, add(bytecode, 0x20), mload(bytecode)) + } + if (instance == address(0)) { + revert Errors.FailedDeployment(); + } + } + + /** + * @dev Deploys and returns the address of a clone that mimics the behavior of `implementation` with custom + * immutable arguments. These are provided through `args` and cannot be changed after deployment. To + * access the arguments within the implementation, use {fetchCloneArgs}. + * + * This function uses the create2 opcode and a `salt` to deterministically deploy the clone. Using the same + * `implementation`, `args` and `salt` multiple times will revert, since the clones cannot be deployed twice + * at the same address. + * + * WARNING: This function does not check if `implementation` has code. A clone that points to an address + * without code cannot be initialized. Initialization calls may appear to be successful when, in reality, they + * have no effect and leave the clone uninitialized, allowing a third party to initialize it later. + */ + function cloneDeterministicWithImmutableArgs( + address implementation, + bytes memory args, + bytes32 salt + ) internal returns (address instance) { + return cloneDeterministicWithImmutableArgs(implementation, args, salt, 0); + } + + /** + * @dev Same as {xref-Clones-cloneDeterministicWithImmutableArgs-address-bytes-bytes32-}[cloneDeterministicWithImmutableArgs], + * but with a `value` parameter to send native currency to the new contract. + * + * WARNING: This function does not check if `implementation` has code. A clone that points to an address + * without code cannot be initialized. Initialization calls may appear to be successful when, in reality, they + * have no effect and leave the clone uninitialized, allowing a third party to initialize it later. + * + * NOTE: Using a non-zero value at creation will require the contract using this function (e.g. a factory) + * to always have enough balance for new deployments. Consider exposing this function under a payable method. + */ + function cloneDeterministicWithImmutableArgs( + address implementation, + bytes memory args, + bytes32 salt, + uint256 value + ) internal returns (address instance) { + bytes memory bytecode = _cloneCodeWithImmutableArgs(implementation, args); + return Create2.deploy(value, salt, bytecode); + } + + /** + * @dev Computes the address of a clone deployed using {Clones-cloneDeterministicWithImmutableArgs}. + */ + function predictDeterministicAddressWithImmutableArgs( + address implementation, + bytes memory args, + bytes32 salt, + address deployer + ) internal pure returns (address predicted) { + bytes memory bytecode = _cloneCodeWithImmutableArgs(implementation, args); + return Create2.computeAddress(salt, keccak256(bytecode), deployer); + } + + /** + * @dev Computes the address of a clone deployed using {Clones-cloneDeterministicWithImmutableArgs}. + */ + function predictDeterministicAddressWithImmutableArgs( + address implementation, + bytes memory args, + bytes32 salt + ) internal view returns (address predicted) { + return predictDeterministicAddressWithImmutableArgs(implementation, args, salt, address(this)); + } + + /** + * @dev Get the immutable args attached to a clone. + * + * - If `instance` is a clone that was deployed using `clone` or `cloneDeterministic`, this + * function will return an empty array. + * - If `instance` is a clone that was deployed using `cloneWithImmutableArgs` or + * `cloneDeterministicWithImmutableArgs`, this function will return the args array used at + * creation. + * - If `instance` is NOT a clone deployed using this library, the behavior is undefined. This + * function should only be used to check addresses that are known to be clones. + */ + function fetchCloneArgs(address instance) internal view returns (bytes memory) { + bytes memory result = new bytes(instance.code.length - 45); // revert if length is too short + assembly ("memory-safe") { + extcodecopy(instance, add(result, 32), 45, mload(result)) + } + return result; + } + + /** + * @dev Helper that prepares the initcode of the proxy with immutable args. + * + * An assembly variant of this function requires copying the `args` array, which can be efficiently done using + * `mcopy`. Unfortunately, that opcode is not available before cancun. A pure solidity implementation using + * abi.encodePacked is more expensive but also more portable and easier to review. + * + * NOTE: https://eips.ethereum.org/EIPS/eip-170[EIP-170] limits the length of the contract code to 24576 bytes. + * With the proxy code taking 45 bytes, that limits the length of the immutable args to 24531 bytes. + */ + function _cloneCodeWithImmutableArgs( + address implementation, + bytes memory args + ) private pure returns (bytes memory) { + if (args.length > 24531) revert CloneArgumentsTooLong(); + return + abi.encodePacked( + hex"61", + uint16(args.length + 45), + hex"3d81600a3d39f3363d3d373d3d3d363d73", + implementation, + hex"5af43d82803e903d91602b57fd5bf3", + args + ); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/proxy/ERC1967/ERC1967Proxy.sol b/dependencies/@openzeppelin-contracts-5.4.0/proxy/ERC1967/ERC1967Proxy.sol new file mode 100644 index 00000000..eb482f6e --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/proxy/ERC1967/ERC1967Proxy.sol @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.2.0) (proxy/ERC1967/ERC1967Proxy.sol) + +pragma solidity ^0.8.22; + +import {Proxy} from "../Proxy.sol"; +import {ERC1967Utils} from "./ERC1967Utils.sol"; + +/** + * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an + * implementation address that can be changed. This address is stored in storage in the location specified by + * https://eips.ethereum.org/EIPS/eip-1967[ERC-1967], so that it doesn't conflict with the storage layout of the + * implementation behind the proxy. + */ +contract ERC1967Proxy is Proxy { + /** + * @dev Initializes the upgradeable proxy with an initial implementation specified by `implementation`. + * + * If `_data` is nonempty, it's used as data in a delegate call to `implementation`. This will typically be an + * encoded function call, and allows initializing the storage of the proxy like a Solidity constructor. + * + * Requirements: + * + * - If `data` is empty, `msg.value` must be zero. + */ + constructor(address implementation, bytes memory _data) payable { + ERC1967Utils.upgradeToAndCall(implementation, _data); + } + + /** + * @dev Returns the current implementation address. + * + * TIP: To get this value clients can read directly from the storage slot shown below (specified by ERC-1967) using + * the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. + * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc` + */ + function _implementation() internal view virtual override returns (address) { + return ERC1967Utils.getImplementation(); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/proxy/ERC1967/ERC1967Utils.sol b/dependencies/@openzeppelin-contracts-5.4.0/proxy/ERC1967/ERC1967Utils.sol new file mode 100644 index 00000000..ffa77cc7 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/proxy/ERC1967/ERC1967Utils.sol @@ -0,0 +1,177 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (proxy/ERC1967/ERC1967Utils.sol) + +pragma solidity ^0.8.21; + +import {IBeacon} from "../beacon/IBeacon.sol"; +import {IERC1967} from "../../interfaces/IERC1967.sol"; +import {Address} from "../../utils/Address.sol"; +import {StorageSlot} from "../../utils/StorageSlot.sol"; + +/** + * @dev This library provides getters and event emitting update functions for + * https://eips.ethereum.org/EIPS/eip-1967[ERC-1967] slots. + */ +library ERC1967Utils { + /** + * @dev Storage slot with the address of the current implementation. + * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1. + */ + // solhint-disable-next-line private-vars-leading-underscore + bytes32 internal constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; + + /** + * @dev The `implementation` of the proxy is invalid. + */ + error ERC1967InvalidImplementation(address implementation); + + /** + * @dev The `admin` of the proxy is invalid. + */ + error ERC1967InvalidAdmin(address admin); + + /** + * @dev The `beacon` of the proxy is invalid. + */ + error ERC1967InvalidBeacon(address beacon); + + /** + * @dev An upgrade function sees `msg.value > 0` that may be lost. + */ + error ERC1967NonPayable(); + + /** + * @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 ERC-1967 implementation slot. + */ + function _setImplementation(address newImplementation) private { + if (newImplementation.code.length == 0) { + revert ERC1967InvalidImplementation(newImplementation); + } + StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value = newImplementation; + } + + /** + * @dev Performs implementation upgrade with additional setup call if data is nonempty. + * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected + * to avoid stuck value in the contract. + * + * Emits an {IERC1967-Upgraded} event. + */ + function upgradeToAndCall(address newImplementation, bytes memory data) internal { + _setImplementation(newImplementation); + emit IERC1967.Upgraded(newImplementation); + + if (data.length > 0) { + Address.functionDelegateCall(newImplementation, data); + } else { + _checkNonPayable(); + } + } + + /** + * @dev Storage slot with the admin of the contract. + * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1. + */ + // solhint-disable-next-line private-vars-leading-underscore + bytes32 internal constant ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; + + /** + * @dev Returns the current admin. + * + * TIP: To get this value clients can read directly from the storage slot shown below (specified by ERC-1967) using + * the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. + * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103` + */ + function getAdmin() internal view returns (address) { + return StorageSlot.getAddressSlot(ADMIN_SLOT).value; + } + + /** + * @dev Stores a new address in the ERC-1967 admin slot. + */ + function _setAdmin(address newAdmin) private { + if (newAdmin == address(0)) { + revert ERC1967InvalidAdmin(address(0)); + } + StorageSlot.getAddressSlot(ADMIN_SLOT).value = newAdmin; + } + + /** + * @dev Changes the admin of the proxy. + * + * Emits an {IERC1967-AdminChanged} event. + */ + function changeAdmin(address newAdmin) internal { + emit IERC1967.AdminChanged(getAdmin(), newAdmin); + _setAdmin(newAdmin); + } + + /** + * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy. + * This is the keccak-256 hash of "eip1967.proxy.beacon" subtracted by 1. + */ + // solhint-disable-next-line private-vars-leading-underscore + bytes32 internal constant BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50; + + /** + * @dev Returns the current beacon. + */ + function getBeacon() internal view returns (address) { + return StorageSlot.getAddressSlot(BEACON_SLOT).value; + } + + /** + * @dev Stores a new beacon in the ERC-1967 beacon slot. + */ + function _setBeacon(address newBeacon) private { + if (newBeacon.code.length == 0) { + revert ERC1967InvalidBeacon(newBeacon); + } + + StorageSlot.getAddressSlot(BEACON_SLOT).value = newBeacon; + + address beaconImplementation = IBeacon(newBeacon).implementation(); + if (beaconImplementation.code.length == 0) { + revert ERC1967InvalidImplementation(beaconImplementation); + } + } + + /** + * @dev Change the beacon and trigger a setup call if data is nonempty. + * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected + * to avoid stuck value in the contract. + * + * Emits an {IERC1967-BeaconUpgraded} event. + * + * CAUTION: Invoking this function has no effect on an instance of {BeaconProxy} since v5, since + * it uses an immutable beacon without looking at the value of the ERC-1967 beacon slot for + * efficiency. + */ + function upgradeBeaconToAndCall(address newBeacon, bytes memory data) internal { + _setBeacon(newBeacon); + emit IERC1967.BeaconUpgraded(newBeacon); + + if (data.length > 0) { + Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data); + } else { + _checkNonPayable(); + } + } + + /** + * @dev Reverts if `msg.value` is not zero. It can be used to avoid `msg.value` stuck in the contract + * if an upgrade doesn't perform an initialization call. + */ + function _checkNonPayable() private { + if (msg.value > 0) { + revert ERC1967NonPayable(); + } + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/proxy/Proxy.sol b/dependencies/@openzeppelin-contracts-5.4.0/proxy/Proxy.sol new file mode 100644 index 00000000..0e736512 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/proxy/Proxy.sol @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.0.0) (proxy/Proxy.sol) + +pragma solidity ^0.8.20; + +/** + * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM + * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to + * be specified by overriding the virtual {_implementation} function. + * + * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a + * different contract through the {_delegate} function. + * + * The success and return data of the delegated call will be returned back to the caller of the proxy. + */ +abstract contract Proxy { + /** + * @dev Delegates the current call to `implementation`. + * + * This function does not return to its internal call site, it will return directly to the external caller. + */ + function _delegate(address implementation) internal virtual { + assembly { + // Copy msg.data. We take full control of memory in this inline assembly + // block because it will not return to Solidity code. We overwrite the + // Solidity scratch pad at memory position 0. + calldatacopy(0, 0, calldatasize()) + + // Call the implementation. + // out and outsize are 0 because we don't know the size yet. + let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0) + + // Copy the returned data. + returndatacopy(0, 0, returndatasize()) + + switch result + // delegatecall returns 0 on error. + case 0 { + revert(0, returndatasize()) + } + default { + return(0, returndatasize()) + } + } + } + + /** + * @dev This is a virtual function that should be overridden so it returns the address to which the fallback + * function and {_fallback} should delegate. + */ + function _implementation() internal view virtual returns (address); + + /** + * @dev Delegates the current call to the address returned by `_implementation()`. + * + * This function does not return to its internal call site, it will return directly to the external caller. + */ + function _fallback() internal virtual { + _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(); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/proxy/beacon/BeaconProxy.sol b/dependencies/@openzeppelin-contracts-5.4.0/proxy/beacon/BeaconProxy.sol new file mode 100644 index 00000000..36558d67 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/proxy/beacon/BeaconProxy.sol @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.2.0) (proxy/beacon/BeaconProxy.sol) + +pragma solidity ^0.8.22; + +import {IBeacon} from "./IBeacon.sol"; +import {Proxy} from "../Proxy.sol"; +import {ERC1967Utils} from "../ERC1967/ERC1967Utils.sol"; + +/** + * @dev This contract implements a proxy that gets the implementation address for each call from an {UpgradeableBeacon}. + * + * The beacon address can only be set once during construction, and cannot be changed afterwards. It is stored in an + * immutable variable to avoid unnecessary storage reads, and also in the beacon storage slot specified by + * https://eips.ethereum.org/EIPS/eip-1967[ERC-1967] so that it can be accessed externally. + * + * CAUTION: Since the beacon address can never be changed, you must ensure that you either control the beacon, or trust + * the beacon to not upgrade the implementation maliciously. + * + * IMPORTANT: Do not use the implementation logic to modify the beacon storage slot. Doing so would leave the proxy in + * an inconsistent state where the beacon storage slot does not match the beacon address. + */ +contract BeaconProxy is Proxy { + // An immutable address for the beacon to avoid unnecessary SLOADs before each delegate call. + address private immutable _beacon; + + /** + * @dev Initializes the proxy with `beacon`. + * + * If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon. This + * will typically be an encoded function call, and allows initializing the storage of the proxy like a Solidity + * constructor. + * + * Requirements: + * + * - `beacon` must be a contract with the interface {IBeacon}. + * - If `data` is empty, `msg.value` must be zero. + */ + constructor(address beacon, bytes memory data) payable { + ERC1967Utils.upgradeBeaconToAndCall(beacon, data); + _beacon = beacon; + } + + /** + * @dev Returns the current implementation address of the associated beacon. + */ + function _implementation() internal view virtual override returns (address) { + return IBeacon(_getBeacon()).implementation(); + } + + /** + * @dev Returns the beacon. + */ + function _getBeacon() internal view virtual returns (address) { + return _beacon; + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/proxy/beacon/IBeacon.sol b/dependencies/@openzeppelin-contracts-5.4.0/proxy/beacon/IBeacon.sol new file mode 100644 index 00000000..f911b15a --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/proxy/beacon/IBeacon.sol @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (proxy/beacon/IBeacon.sol) + +pragma solidity >=0.4.16; + +/** + * @dev This is the interface that {BeaconProxy} expects of its beacon. + */ +interface IBeacon { + /** + * @dev Must return an address that can be used as a delegate call target. + * + * {UpgradeableBeacon} will check that this address is a contract. + */ + function implementation() external view returns (address); +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/proxy/beacon/UpgradeableBeacon.sol b/dependencies/@openzeppelin-contracts-5.4.0/proxy/beacon/UpgradeableBeacon.sol new file mode 100644 index 00000000..8db9bd23 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/proxy/beacon/UpgradeableBeacon.sol @@ -0,0 +1,70 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.0.0) (proxy/beacon/UpgradeableBeacon.sol) + +pragma solidity ^0.8.20; + +import {IBeacon} from "./IBeacon.sol"; +import {Ownable} from "../../access/Ownable.sol"; + +/** + * @dev This contract is used in conjunction with one or more instances of {BeaconProxy} to determine their + * implementation contract, which is where they will delegate all function calls. + * + * An owner is able to change the implementation the beacon points to, thus upgrading the proxies that use this beacon. + */ +contract UpgradeableBeacon is IBeacon, Ownable { + address private _implementation; + + /** + * @dev The `implementation` of the beacon is invalid. + */ + error BeaconInvalidImplementation(address implementation); + + /** + * @dev Emitted when the implementation returned by the beacon is changed. + */ + event Upgraded(address indexed implementation); + + /** + * @dev Sets the address of the initial implementation, and the initial owner who can upgrade the beacon. + */ + constructor(address implementation_, address initialOwner) Ownable(initialOwner) { + _setImplementation(implementation_); + } + + /** + * @dev Returns the current implementation address. + */ + function implementation() public view virtual returns (address) { + return _implementation; + } + + /** + * @dev Upgrades the beacon to a new implementation. + * + * Emits an {Upgraded} event. + * + * Requirements: + * + * - msg.sender must be the owner of the contract. + * - `newImplementation` must be a contract. + */ + function upgradeTo(address newImplementation) public virtual onlyOwner { + _setImplementation(newImplementation); + } + + /** + * @dev Sets the implementation contract address for this beacon + * + * Requirements: + * + * - `newImplementation` must be a contract. + */ + function _setImplementation(address newImplementation) private { + if (newImplementation.code.length == 0) { + revert BeaconInvalidImplementation(newImplementation); + } + _implementation = newImplementation; + emit Upgraded(newImplementation); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/proxy/transparent/ProxyAdmin.sol b/dependencies/@openzeppelin-contracts-5.4.0/proxy/transparent/ProxyAdmin.sol new file mode 100644 index 00000000..eefd49a8 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/proxy/transparent/ProxyAdmin.sol @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.2.0) (proxy/transparent/ProxyAdmin.sol) + +pragma solidity ^0.8.22; + +import {ITransparentUpgradeableProxy} from "./TransparentUpgradeableProxy.sol"; +import {Ownable} from "../../access/Ownable.sol"; + +/** + * @dev This is an auxiliary contract meant to be assigned as the admin of a {TransparentUpgradeableProxy}. For an + * explanation of why you would want to use this see the documentation for {TransparentUpgradeableProxy}. + */ +contract ProxyAdmin is Ownable { + /** + * @dev The version of the upgrade interface of the contract. If this getter is missing, both `upgrade(address,address)` + * and `upgradeAndCall(address,address,bytes)` are present, and `upgrade` must be used if no function should be called, + * while `upgradeAndCall` will invoke the `receive` function if the third argument is the empty byte string. + * If the getter returns `"5.0.0"`, only `upgradeAndCall(address,address,bytes)` is present, and the third argument must + * be the empty byte string if no function should be called, making it impossible to invoke the `receive` function + * during an upgrade. + */ + string public constant UPGRADE_INTERFACE_VERSION = "5.0.0"; + + /** + * @dev Sets the initial owner who can perform upgrades. + */ + constructor(address initialOwner) Ownable(initialOwner) {} + + /** + * @dev Upgrades `proxy` to `implementation` and calls a function on the new implementation. + * See {TransparentUpgradeableProxy-_dispatchUpgradeToAndCall}. + * + * Requirements: + * + * - This contract must be the admin of `proxy`. + * - If `data` is empty, `msg.value` must be zero. + */ + function upgradeAndCall( + ITransparentUpgradeableProxy proxy, + address implementation, + bytes memory data + ) public payable virtual onlyOwner { + proxy.upgradeToAndCall{value: msg.value}(implementation, data); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/proxy/transparent/TransparentUpgradeableProxy.sol b/dependencies/@openzeppelin-contracts-5.4.0/proxy/transparent/TransparentUpgradeableProxy.sol new file mode 100644 index 00000000..21af0e31 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/proxy/transparent/TransparentUpgradeableProxy.sol @@ -0,0 +1,118 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.2.0) (proxy/transparent/TransparentUpgradeableProxy.sol) + +pragma solidity ^0.8.22; + +import {ERC1967Utils} from "../ERC1967/ERC1967Utils.sol"; +import {ERC1967Proxy} from "../ERC1967/ERC1967Proxy.sol"; +import {IERC1967} from "../../interfaces/IERC1967.sol"; +import {ProxyAdmin} from "./ProxyAdmin.sol"; + +/** + * @dev Interface for {TransparentUpgradeableProxy}. In order to implement transparency, {TransparentUpgradeableProxy} + * does not implement this interface directly, and its upgradeability mechanism is implemented by an internal dispatch + * mechanism. The compiler is unaware that these functions are implemented by {TransparentUpgradeableProxy} and will not + * include them in the ABI so this interface must be used to interact with it. + */ +interface ITransparentUpgradeableProxy is IERC1967 { + /// @dev See {UUPSUpgradeable-upgradeToAndCall} + function upgradeToAndCall(address newImplementation, bytes calldata data) external payable; +} + +/** + * @dev This contract implements a proxy that is upgradeable through an associated {ProxyAdmin} instance. + * + * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector + * clashing], which can potentially be used in an attack, this contract uses the + * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two + * things that go hand in hand: + * + * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if + * that call matches the {ITransparentUpgradeableProxy-upgradeToAndCall} function exposed by the proxy itself. + * 2. If the admin calls the proxy, it can call the `upgradeToAndCall` function but any other call won't be forwarded to + * the implementation. If the admin tries to call a function on the implementation it will fail with an error indicating + * the proxy admin cannot fallback to the target implementation. + * + * These properties mean that the admin account can only be used for upgrading the proxy, so it's best if it's a + * dedicated account that is not used for anything else. This will avoid headaches due to sudden errors when trying to + * call a function from the proxy implementation. For this reason, the proxy deploys an instance of {ProxyAdmin} and + * allows upgrades only if they come through it. You should think of the `ProxyAdmin` instance as the administrative + * interface of the proxy, including the ability to change who can trigger upgrades by transferring ownership. + * + * NOTE: The real interface of this proxy is that defined in `ITransparentUpgradeableProxy`. This contract does not + * inherit from that interface, and instead `upgradeToAndCall` is implicitly implemented using a custom dispatch + * mechanism in `_fallback`. Consequently, the compiler will not produce an ABI for this contract. This is necessary to + * fully implement transparency without decoding reverts caused by selector clashes between the proxy and the + * implementation. + * + * NOTE: This proxy does not inherit from {Context} deliberately. The {ProxyAdmin} of this contract won't send a + * meta-transaction in any way, and any other meta-transaction setup should be made in the implementation contract. + * + * IMPORTANT: This contract avoids unnecessary storage reads by setting the admin only during construction as an + * immutable variable, preventing any changes thereafter. However, the admin slot defined in ERC-1967 can still be + * overwritten by the implementation logic pointed to by this proxy. In such cases, the contract may end up in an + * undesirable state where the admin slot is different from the actual admin. Relying on the value of the admin slot + * is generally fine if the implementation is trusted. + * + * WARNING: It is not recommended to extend this contract to add additional external functions. If you do so, the + * compiler will not check that there are no selector conflicts, due to the note above. A selector clash between any new + * function and the functions declared in {ITransparentUpgradeableProxy} will be resolved in favor of the new one. This + * could render the `upgradeToAndCall` function inaccessible, preventing upgradeability and compromising transparency. + */ +contract TransparentUpgradeableProxy is ERC1967Proxy { + // An immutable address for the admin to avoid unnecessary SLOADs before each call + // at the expense of removing the ability to change the admin once it's set. + // This is acceptable if the admin is always a ProxyAdmin instance or similar contract + // with its own ability to transfer the permissions to another account. + address private immutable _admin; + + /** + * @dev The proxy caller is the current admin, and can't fallback to the proxy target. + */ + error ProxyDeniedAdminAccess(); + + /** + * @dev Initializes an upgradeable proxy managed by an instance of a {ProxyAdmin} with an `initialOwner`, + * backed by the implementation at `_logic`, and optionally initialized with `_data` as explained in + * {ERC1967Proxy-constructor}. + */ + constructor(address _logic, address initialOwner, bytes memory _data) payable ERC1967Proxy(_logic, _data) { + _admin = address(new ProxyAdmin(initialOwner)); + // Set the storage value and emit an event for ERC-1967 compatibility + ERC1967Utils.changeAdmin(_proxyAdmin()); + } + + /** + * @dev Returns the admin of this proxy. + */ + function _proxyAdmin() internal view virtual returns (address) { + return _admin; + } + + /** + * @dev If caller is the admin process the call internally, otherwise transparently fallback to the proxy behavior. + */ + function _fallback() internal virtual override { + if (msg.sender == _proxyAdmin()) { + if (msg.sig != ITransparentUpgradeableProxy.upgradeToAndCall.selector) { + revert ProxyDeniedAdminAccess(); + } else { + _dispatchUpgradeToAndCall(); + } + } else { + super._fallback(); + } + } + + /** + * @dev Upgrade the implementation of the proxy. See {ERC1967Utils-upgradeToAndCall}. + * + * Requirements: + * + * - If `data` is empty, `msg.value` must be zero. + */ + function _dispatchUpgradeToAndCall() private { + (address newImplementation, bytes memory data) = abi.decode(msg.data[4:], (address, bytes)); + ERC1967Utils.upgradeToAndCall(newImplementation, data); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/proxy/utils/Initializable.sol b/dependencies/@openzeppelin-contracts-5.4.0/proxy/utils/Initializable.sol new file mode 100644 index 00000000..0d05fdb0 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/proxy/utils/Initializable.sol @@ -0,0 +1,238 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.3.0) (proxy/utils/Initializable.sol) + +pragma solidity ^0.8.20; + +/** + * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed + * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an + * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer + * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. + * + * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be + * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in + * case an upgrade adds a module that needs to be initialized. + * + * For example: + * + * [.hljs-theme-light.nopadding] + * ```solidity + * contract MyToken is ERC20Upgradeable { + * function initialize() initializer public { + * __ERC20_init("MyToken", "MTK"); + * } + * } + * + * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { + * function initializeV2() reinitializer(2) public { + * __ERC20Permit_init("MyToken"); + * } + * } + * ``` + * + * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as + * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. + * + * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure + * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. + * + * [CAUTION] + * ==== + * Avoid leaving a contract uninitialized. + * + * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation + * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke + * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: + * + * [.hljs-theme-light.nopadding] + * ``` + * /// @custom:oz-upgrades-unsafe-allow constructor + * constructor() { + * _disableInitializers(); + * } + * ``` + * ==== + */ +abstract contract Initializable { + /** + * @dev Storage of the initializable contract. + * + * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions + * when using with upgradeable contracts. + * + * @custom:storage-location erc7201:openzeppelin.storage.Initializable + */ + struct InitializableStorage { + /** + * @dev Indicates that the contract has been initialized. + */ + uint64 _initialized; + /** + * @dev Indicates that the contract is in the process of being initialized. + */ + bool _initializing; + } + + // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Initializable")) - 1)) & ~bytes32(uint256(0xff)) + bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00; + + /** + * @dev The contract is already initialized. + */ + error InvalidInitialization(); + + /** + * @dev The contract is not initializing. + */ + error NotInitializing(); + + /** + * @dev Triggered when the contract has been initialized or reinitialized. + */ + event Initialized(uint64 version); + + /** + * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, + * `onlyInitializing` functions can be used to initialize parent contracts. + * + * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any + * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in + * production. + * + * Emits an {Initialized} event. + */ + modifier initializer() { + // solhint-disable-next-line var-name-mixedcase + InitializableStorage storage $ = _getInitializableStorage(); + + // Cache values to avoid duplicated sloads + bool isTopLevelCall = !$._initializing; + uint64 initialized = $._initialized; + + // Allowed calls: + // - initialSetup: the contract is not in the initializing state and no previous version was + // initialized + // - construction: the contract is initialized at version 1 (no reinitialization) and the + // current contract is just being deployed + bool initialSetup = initialized == 0 && isTopLevelCall; + bool construction = initialized == 1 && address(this).code.length == 0; + + if (!initialSetup && !construction) { + revert InvalidInitialization(); + } + $._initialized = 1; + if (isTopLevelCall) { + $._initializing = true; + } + _; + if (isTopLevelCall) { + $._initializing = false; + emit Initialized(1); + } + } + + /** + * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the + * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be + * used to initialize parent contracts. + * + * A reinitializer may be used after the original initialization step. This is essential to configure modules that + * are added through upgrades and that require initialization. + * + * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` + * cannot be nested. If one is invoked in the context of another, execution will revert. + * + * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in + * a contract, executing them in the right order is up to the developer or operator. + * + * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization. + * + * Emits an {Initialized} event. + */ + modifier reinitializer(uint64 version) { + // solhint-disable-next-line var-name-mixedcase + InitializableStorage storage $ = _getInitializableStorage(); + + if ($._initializing || $._initialized >= version) { + revert InvalidInitialization(); + } + $._initialized = version; + $._initializing = true; + _; + $._initializing = false; + emit Initialized(version); + } + + /** + * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the + * {initializer} and {reinitializer} modifiers, directly or indirectly. + */ + modifier onlyInitializing() { + _checkInitializing(); + _; + } + + /** + * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}. + */ + function _checkInitializing() internal view virtual { + if (!_isInitializing()) { + revert NotInitializing(); + } + } + + /** + * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. + * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized + * to any version. It is recommended to use this to lock implementation contracts that are designed to be called + * through proxies. + * + * Emits an {Initialized} event the first time it is successfully executed. + */ + function _disableInitializers() internal virtual { + // solhint-disable-next-line var-name-mixedcase + InitializableStorage storage $ = _getInitializableStorage(); + + if ($._initializing) { + revert InvalidInitialization(); + } + if ($._initialized != type(uint64).max) { + $._initialized = type(uint64).max; + emit Initialized(type(uint64).max); + } + } + + /** + * @dev Returns the highest version that has been initialized. See {reinitializer}. + */ + function _getInitializedVersion() internal view returns (uint64) { + return _getInitializableStorage()._initialized; + } + + /** + * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. + */ + function _isInitializing() internal view returns (bool) { + return _getInitializableStorage()._initializing; + } + + /** + * @dev Pointer to storage slot. Allows integrators to override it with a custom storage location. + * + * NOTE: Consider following the ERC-7201 formula to derive storage locations. + */ + function _initializableStorageSlot() internal pure virtual returns (bytes32) { + return INITIALIZABLE_STORAGE; + } + + /** + * @dev Returns a pointer to the storage namespace. + */ + // solhint-disable-next-line var-name-mixedcase + function _getInitializableStorage() private pure returns (InitializableStorage storage $) { + bytes32 slot = _initializableStorageSlot(); + assembly { + $.slot := slot + } + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/proxy/utils/UUPSUpgradeable.sol b/dependencies/@openzeppelin-contracts-5.4.0/proxy/utils/UUPSUpgradeable.sol new file mode 100644 index 00000000..d0f58427 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/proxy/utils/UUPSUpgradeable.sol @@ -0,0 +1,146 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.3.0) (proxy/utils/UUPSUpgradeable.sol) + +pragma solidity ^0.8.22; + +import {IERC1822Proxiable} from "../../interfaces/draft-IERC1822.sol"; +import {ERC1967Utils} from "../ERC1967/ERC1967Utils.sol"; + +/** + * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an + * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy. + * + * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is + * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing + * `UUPSUpgradeable` with a custom implementation of upgrades. + * + * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism. + */ +abstract contract UUPSUpgradeable is IERC1822Proxiable { + /// @custom:oz-upgrades-unsafe-allow state-variable-immutable + address private immutable __self = address(this); + + /** + * @dev The version of the upgrade interface of the contract. If this getter is missing, both `upgradeTo(address)` + * and `upgradeToAndCall(address,bytes)` are present, and `upgradeTo` must be used if no function should be called, + * while `upgradeToAndCall` will invoke the `receive` function if the second argument is the empty byte string. + * If the getter returns `"5.0.0"`, only `upgradeToAndCall(address,bytes)` is present, and the second argument must + * be the empty byte string if no function should be called, making it impossible to invoke the `receive` function + * during an upgrade. + */ + string public constant UPGRADE_INTERFACE_VERSION = "5.0.0"; + + /** + * @dev The call is from an unauthorized context. + */ + error UUPSUnauthorizedCallContext(); + + /** + * @dev The storage `slot` is unsupported as a UUID. + */ + error UUPSUnsupportedProxiableUUID(bytes32 slot); + + /** + * @dev Check that the execution is being performed through a delegatecall call and that the execution context is + * a proxy contract with an implementation (as defined in ERC-1967) pointing to self. This should only be the case + * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a + * function through ERC-1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to + * fail. + */ + modifier onlyProxy() { + _checkProxy(); + _; + } + + /** + * @dev Check that the execution is not being performed through a delegate call. This allows a function to be + * callable on the implementing contract but not through proxies. + */ + modifier notDelegated() { + _checkNotDelegated(); + _; + } + + /** + * @dev Implementation of the ERC-1822 {proxiableUUID} function. This returns the storage slot used by the + * implementation. It is used to validate the implementation's compatibility when performing an upgrade. + * + * 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. This is guaranteed by the `notDelegated` modifier. + */ + function proxiableUUID() external view virtual notDelegated returns (bytes32) { + return ERC1967Utils.IMPLEMENTATION_SLOT; + } + + /** + * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call + * encoded in `data`. + * + * Calls {_authorizeUpgrade}. + * + * Emits an {Upgraded} event. + * + * @custom:oz-upgrades-unsafe-allow-reachable delegatecall + */ + function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy { + _authorizeUpgrade(newImplementation); + _upgradeToAndCallUUPS(newImplementation, data); + } + + /** + * @dev Reverts if the execution is not performed via delegatecall or the execution + * context is not of a proxy with an ERC-1967 compliant implementation pointing to self. + */ + function _checkProxy() internal view virtual { + if ( + address(this) == __self || // Must be called through delegatecall + ERC1967Utils.getImplementation() != __self // Must be called through an active proxy + ) { + revert UUPSUnauthorizedCallContext(); + } + } + + /** + * @dev Reverts if the execution is performed via delegatecall. + * See {notDelegated}. + */ + function _checkNotDelegated() internal view virtual { + if (address(this) != __self) { + // Must not be called through delegatecall + revert UUPSUnauthorizedCallContext(); + } + } + + /** + * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by + * {upgradeToAndCall}. + * + * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}. + * + * ```solidity + * function _authorizeUpgrade(address) internal onlyOwner {} + * ``` + */ + function _authorizeUpgrade(address newImplementation) internal virtual; + + /** + * @dev Performs an implementation upgrade with a security check for UUPS proxies, and additional setup call. + * + * As a security check, {proxiableUUID} is invoked in the new implementation, and the return value + * is expected to be the implementation slot in ERC-1967. + * + * Emits an {IERC1967-Upgraded} event. + */ + function _upgradeToAndCallUUPS(address newImplementation, bytes memory data) private { + try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) { + if (slot != ERC1967Utils.IMPLEMENTATION_SLOT) { + revert UUPSUnsupportedProxiableUUID(slot); + } + ERC1967Utils.upgradeToAndCall(newImplementation, data); + } catch { + // The implementation is not UUPS + revert ERC1967Utils.ERC1967InvalidImplementation(newImplementation); + } + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/token/ERC1155/ERC1155.sol b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC1155/ERC1155.sol new file mode 100644 index 00000000..8582e0cb --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC1155/ERC1155.sol @@ -0,0 +1,389 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC1155/ERC1155.sol) + +pragma solidity ^0.8.20; + +import {IERC1155} from "./IERC1155.sol"; +import {IERC1155MetadataURI} from "./extensions/IERC1155MetadataURI.sol"; +import {ERC1155Utils} from "./utils/ERC1155Utils.sol"; +import {Context} from "../../utils/Context.sol"; +import {IERC165, ERC165} from "../../utils/introspection/ERC165.sol"; +import {Arrays} from "../../utils/Arrays.sol"; +import {IERC1155Errors} from "../../interfaces/draft-IERC6093.sol"; + +/** + * @dev Implementation of the basic standard multi-token. + * See https://eips.ethereum.org/EIPS/eip-1155 + * Originally based on code by Enjin: https://github.com/enjin/erc-1155 + */ +abstract contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI, IERC1155Errors { + using Arrays for uint256[]; + using Arrays for address[]; + + mapping(uint256 id => mapping(address account => uint256)) private _balances; + + mapping(address account => mapping(address operator => bool)) private _operatorApprovals; + + // Used as the URI for all token types by relying on ID substitution, e.g. https://token-cdn-domain/{id}.json + string private _uri; + + /** + * @dev See {_setURI}. + */ + constructor(string memory uri_) { + _setURI(uri_); + } + + /// @inheritdoc IERC165 + function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { + return + interfaceId == type(IERC1155).interfaceId || + interfaceId == type(IERC1155MetadataURI).interfaceId || + super.supportsInterface(interfaceId); + } + + /** + * @dev See {IERC1155MetadataURI-uri}. + * + * This implementation returns the same URI for *all* token types. It relies + * on the token type ID substitution mechanism + * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the ERC]. + * + * Clients calling this function must replace the `\{id\}` substring with the + * actual token type ID. + */ + function uri(uint256 /* id */) public view virtual returns (string memory) { + return _uri; + } + + /// @inheritdoc IERC1155 + function balanceOf(address account, uint256 id) public view virtual returns (uint256) { + return _balances[id][account]; + } + + /** + * @dev See {IERC1155-balanceOfBatch}. + * + * Requirements: + * + * - `accounts` and `ids` must have the same length. + */ + function balanceOfBatch( + address[] memory accounts, + uint256[] memory ids + ) public view virtual returns (uint256[] memory) { + if (accounts.length != ids.length) { + revert ERC1155InvalidArrayLength(ids.length, accounts.length); + } + + uint256[] memory batchBalances = new uint256[](accounts.length); + + for (uint256 i = 0; i < accounts.length; ++i) { + batchBalances[i] = balanceOf(accounts.unsafeMemoryAccess(i), ids.unsafeMemoryAccess(i)); + } + + return batchBalances; + } + + /// @inheritdoc IERC1155 + function setApprovalForAll(address operator, bool approved) public virtual { + _setApprovalForAll(_msgSender(), operator, approved); + } + + /// @inheritdoc IERC1155 + function isApprovedForAll(address account, address operator) public view virtual returns (bool) { + return _operatorApprovals[account][operator]; + } + + /// @inheritdoc IERC1155 + function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes memory data) public virtual { + address sender = _msgSender(); + if (from != sender && !isApprovedForAll(from, sender)) { + revert ERC1155MissingApprovalForAll(sender, from); + } + _safeTransferFrom(from, to, id, value, data); + } + + /// @inheritdoc IERC1155 + function safeBatchTransferFrom( + address from, + address to, + uint256[] memory ids, + uint256[] memory values, + bytes memory data + ) public virtual { + address sender = _msgSender(); + if (from != sender && !isApprovedForAll(from, sender)) { + revert ERC1155MissingApprovalForAll(sender, from); + } + _safeBatchTransferFrom(from, to, ids, values, data); + } + + /** + * @dev Transfers a `value` amount of tokens of type `id` from `from` to `to`. Will mint (or burn) if `from` + * (or `to`) is the zero address. + * + * Emits a {TransferSingle} event if the arrays contain one element, and {TransferBatch} otherwise. + * + * Requirements: + * + * - If `to` refers to a smart contract, it must implement either {IERC1155Receiver-onERC1155Received} + * or {IERC1155Receiver-onERC1155BatchReceived} and return the acceptance magic value. + * - `ids` and `values` must have the same length. + * + * NOTE: The ERC-1155 acceptance check is not performed in this function. See {_updateWithAcceptanceCheck} instead. + */ + function _update(address from, address to, uint256[] memory ids, uint256[] memory values) internal virtual { + if (ids.length != values.length) { + revert ERC1155InvalidArrayLength(ids.length, values.length); + } + + address operator = _msgSender(); + + for (uint256 i = 0; i < ids.length; ++i) { + uint256 id = ids.unsafeMemoryAccess(i); + uint256 value = values.unsafeMemoryAccess(i); + + if (from != address(0)) { + uint256 fromBalance = _balances[id][from]; + if (fromBalance < value) { + revert ERC1155InsufficientBalance(from, fromBalance, value, id); + } + unchecked { + // Overflow not possible: value <= fromBalance + _balances[id][from] = fromBalance - value; + } + } + + if (to != address(0)) { + _balances[id][to] += value; + } + } + + if (ids.length == 1) { + uint256 id = ids.unsafeMemoryAccess(0); + uint256 value = values.unsafeMemoryAccess(0); + emit TransferSingle(operator, from, to, id, value); + } else { + emit TransferBatch(operator, from, to, ids, values); + } + } + + /** + * @dev Version of {_update} that performs the token acceptance check by calling + * {IERC1155Receiver-onERC1155Received} or {IERC1155Receiver-onERC1155BatchReceived} on the receiver address if it + * contains code (eg. is a smart contract at the moment of execution). + * + * IMPORTANT: Overriding this function is discouraged because it poses a reentrancy risk from the receiver. So any + * update to the contract state after this function would break the check-effect-interaction pattern. Consider + * overriding {_update} instead. + */ + function _updateWithAcceptanceCheck( + address from, + address to, + uint256[] memory ids, + uint256[] memory values, + bytes memory data + ) internal virtual { + _update(from, to, ids, values); + if (to != address(0)) { + address operator = _msgSender(); + if (ids.length == 1) { + uint256 id = ids.unsafeMemoryAccess(0); + uint256 value = values.unsafeMemoryAccess(0); + ERC1155Utils.checkOnERC1155Received(operator, from, to, id, value, data); + } else { + ERC1155Utils.checkOnERC1155BatchReceived(operator, from, to, ids, values, data); + } + } + } + + /** + * @dev Transfers a `value` tokens of token type `id` from `from` to `to`. + * + * Emits a {TransferSingle} event. + * + * Requirements: + * + * - `to` cannot be the zero address. + * - `from` must have a balance of tokens of type `id` of at least `value` amount. + * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the + * acceptance magic value. + */ + function _safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes memory data) internal { + if (to == address(0)) { + revert ERC1155InvalidReceiver(address(0)); + } + if (from == address(0)) { + revert ERC1155InvalidSender(address(0)); + } + (uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value); + _updateWithAcceptanceCheck(from, to, ids, values, data); + } + + /** + * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_safeTransferFrom}. + * + * Emits a {TransferBatch} event. + * + * Requirements: + * + * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the + * acceptance magic value. + * - `ids` and `values` must have the same length. + */ + function _safeBatchTransferFrom( + address from, + address to, + uint256[] memory ids, + uint256[] memory values, + bytes memory data + ) internal { + if (to == address(0)) { + revert ERC1155InvalidReceiver(address(0)); + } + if (from == address(0)) { + revert ERC1155InvalidSender(address(0)); + } + _updateWithAcceptanceCheck(from, to, ids, values, data); + } + + /** + * @dev Sets a new URI for all token types, by relying on the token type ID + * substitution mechanism + * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the ERC]. + * + * By this mechanism, any occurrence of the `\{id\}` substring in either the + * URI or any of the values in the JSON file at said URI will be replaced by + * clients with the token type ID. + * + * For example, the `https://token-cdn-domain/\{id\}.json` URI would be + * interpreted by clients as + * `https://token-cdn-domain/000000000000000000000000000000000000000000000000000000000004cce0.json` + * for token type ID 0x4cce0. + * + * See {uri}. + * + * Because these URIs cannot be meaningfully represented by the {URI} event, + * this function emits no events. + */ + function _setURI(string memory newuri) internal virtual { + _uri = newuri; + } + + /** + * @dev Creates a `value` amount of tokens of type `id`, and assigns them to `to`. + * + * Emits a {TransferSingle} event. + * + * Requirements: + * + * - `to` cannot be the zero address. + * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the + * acceptance magic value. + */ + function _mint(address to, uint256 id, uint256 value, bytes memory data) internal { + if (to == address(0)) { + revert ERC1155InvalidReceiver(address(0)); + } + (uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value); + _updateWithAcceptanceCheck(address(0), to, ids, values, data); + } + + /** + * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_mint}. + * + * Emits a {TransferBatch} event. + * + * Requirements: + * + * - `ids` and `values` must have the same length. + * - `to` cannot be the zero address. + * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the + * acceptance magic value. + */ + function _mintBatch(address to, uint256[] memory ids, uint256[] memory values, bytes memory data) internal { + if (to == address(0)) { + revert ERC1155InvalidReceiver(address(0)); + } + _updateWithAcceptanceCheck(address(0), to, ids, values, data); + } + + /** + * @dev Destroys a `value` amount of tokens of type `id` from `from` + * + * Emits a {TransferSingle} event. + * + * Requirements: + * + * - `from` cannot be the zero address. + * - `from` must have at least `value` amount of tokens of type `id`. + */ + function _burn(address from, uint256 id, uint256 value) internal { + if (from == address(0)) { + revert ERC1155InvalidSender(address(0)); + } + (uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value); + _updateWithAcceptanceCheck(from, address(0), ids, values, ""); + } + + /** + * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_burn}. + * + * Emits a {TransferBatch} event. + * + * Requirements: + * + * - `from` cannot be the zero address. + * - `from` must have at least `value` amount of tokens of type `id`. + * - `ids` and `values` must have the same length. + */ + function _burnBatch(address from, uint256[] memory ids, uint256[] memory values) internal { + if (from == address(0)) { + revert ERC1155InvalidSender(address(0)); + } + _updateWithAcceptanceCheck(from, address(0), ids, values, ""); + } + + /** + * @dev Approve `operator` to operate on all of `owner` tokens + * + * Emits an {ApprovalForAll} event. + * + * Requirements: + * + * - `operator` cannot be the zero address. + */ + function _setApprovalForAll(address owner, address operator, bool approved) internal virtual { + if (operator == address(0)) { + revert ERC1155InvalidOperator(address(0)); + } + _operatorApprovals[owner][operator] = approved; + emit ApprovalForAll(owner, operator, approved); + } + + /** + * @dev Creates an array in memory with only one value for each of the elements provided. + */ + function _asSingletonArrays( + uint256 element1, + uint256 element2 + ) private pure returns (uint256[] memory array1, uint256[] memory array2) { + assembly ("memory-safe") { + // Load the free memory pointer + array1 := mload(0x40) + // Set array length to 1 + mstore(array1, 1) + // Store the single element at the next word after the length (where content starts) + mstore(add(array1, 0x20), element1) + + // Repeat for next array locating it right after the first array + array2 := add(array1, 0x40) + mstore(array2, 1) + mstore(add(array2, 0x20), element2) + + // Update the free memory pointer by pointing after the second array + mstore(0x40, add(array2, 0x40)) + } + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/token/ERC1155/IERC1155.sol b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC1155/IERC1155.sol new file mode 100644 index 00000000..f0170845 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC1155/IERC1155.sol @@ -0,0 +1,123 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC1155/IERC1155.sol) + +pragma solidity >=0.6.2; + +import {IERC165} from "../../utils/introspection/IERC165.sol"; + +/** + * @dev Required interface of an ERC-1155 compliant contract, as defined in the + * https://eips.ethereum.org/EIPS/eip-1155[ERC]. + */ +interface IERC1155 is IERC165 { + /** + * @dev Emitted when `value` amount of tokens of type `id` are transferred from `from` to `to` by `operator`. + */ + event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value); + + /** + * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all + * transfers. + */ + event TransferBatch( + address indexed operator, + address indexed from, + address indexed to, + uint256[] ids, + uint256[] values + ); + + /** + * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to + * `approved`. + */ + event ApprovalForAll(address indexed account, address indexed operator, bool approved); + + /** + * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI. + * + * If an {URI} event was emitted for `id`, the standard + * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value + * returned by {IERC1155MetadataURI-uri}. + */ + event URI(string value, uint256 indexed id); + + /** + * @dev Returns the value of tokens of token type `id` owned by `account`. + */ + function balanceOf(address account, uint256 id) external view returns (uint256); + + /** + * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}. + * + * Requirements: + * + * - `accounts` and `ids` must have the same length. + */ + function balanceOfBatch( + address[] calldata accounts, + uint256[] calldata ids + ) external view returns (uint256[] memory); + + /** + * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`, + * + * Emits an {ApprovalForAll} event. + * + * Requirements: + * + * - `operator` cannot be the zero address. + */ + function setApprovalForAll(address operator, bool approved) external; + + /** + * @dev Returns true if `operator` is approved to transfer ``account``'s tokens. + * + * See {setApprovalForAll}. + */ + function isApprovedForAll(address account, address operator) external view returns (bool); + + /** + * @dev Transfers a `value` amount of tokens of type `id` from `from` to `to`. + * + * WARNING: This function can potentially allow a reentrancy attack when transferring tokens + * to an untrusted contract, when invoking {IERC1155Receiver-onERC1155Received} on the receiver. + * Ensure to follow the checks-effects-interactions pattern and consider employing + * reentrancy guards when interacting with untrusted contracts. + * + * Emits a {TransferSingle} event. + * + * Requirements: + * + * - `to` cannot be the zero address. + * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}. + * - `from` must have a balance of tokens of type `id` of at least `value` amount. + * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the + * acceptance magic value. + */ + function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes calldata data) external; + + /** + * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}. + * + * WARNING: This function can potentially allow a reentrancy attack when transferring tokens + * to an untrusted contract, when invoking {IERC1155Receiver-onERC1155BatchReceived} on the receiver. + * Ensure to follow the checks-effects-interactions pattern and consider employing + * reentrancy guards when interacting with untrusted contracts. + * + * Emits either a {TransferSingle} or a {TransferBatch} event, depending on the length of the array arguments. + * + * Requirements: + * + * - `ids` and `values` must have the same length. + * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the + * acceptance magic value. + */ + function safeBatchTransferFrom( + address from, + address to, + uint256[] calldata ids, + uint256[] calldata values, + bytes calldata data + ) external; +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/token/ERC1155/IERC1155Receiver.sol b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC1155/IERC1155Receiver.sol new file mode 100644 index 00000000..f27b8976 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC1155/IERC1155Receiver.sol @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC1155/IERC1155Receiver.sol) + +pragma solidity >=0.6.2; + +import {IERC165} from "../../utils/introspection/IERC165.sol"; + +/** + * @dev Interface that must be implemented by smart contracts in order to receive + * ERC-1155 token transfers. + */ +interface IERC1155Receiver is IERC165 { + /** + * @dev Handles the receipt of a single ERC-1155 token type. This function is + * called at the end of a `safeTransferFrom` after the balance has been updated. + * + * NOTE: To accept the transfer, this must return + * `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` + * (i.e. 0xf23a6e61, or its own function selector). + * + * @param operator The address which initiated the transfer (i.e. msg.sender) + * @param from The address which previously owned the token + * @param id The ID of the token being transferred + * @param value The amount of tokens being transferred + * @param data Additional data with no specified format + * @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed + */ + function onERC1155Received( + address operator, + address from, + uint256 id, + uint256 value, + bytes calldata data + ) external returns (bytes4); + + /** + * @dev Handles the receipt of a multiple ERC-1155 token types. This function + * is called at the end of a `safeBatchTransferFrom` after the balances have + * been updated. + * + * NOTE: To accept the transfer(s), this must return + * `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` + * (i.e. 0xbc197c81, or its own function selector). + * + * @param operator The address which initiated the batch transfer (i.e. msg.sender) + * @param from The address which previously owned the token + * @param ids An array containing ids of each token being transferred (order and length must match values array) + * @param values An array containing amounts of each token being transferred (order and length must match ids array) + * @param data Additional data with no specified format + * @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed + */ + function onERC1155BatchReceived( + address operator, + address from, + uint256[] calldata ids, + uint256[] calldata values, + bytes calldata data + ) external returns (bytes4); +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/token/ERC1155/extensions/ERC1155Burnable.sol b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC1155/extensions/ERC1155Burnable.sol new file mode 100644 index 00000000..fd6ad61d --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC1155/extensions/ERC1155Burnable.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC1155/extensions/ERC1155Burnable.sol) + +pragma solidity ^0.8.20; + +import {ERC1155} from "../ERC1155.sol"; + +/** + * @dev Extension of {ERC1155} that allows token holders to destroy both their + * own tokens and those that they have been approved to use. + */ +abstract contract ERC1155Burnable is ERC1155 { + function burn(address account, uint256 id, uint256 value) public virtual { + if (account != _msgSender() && !isApprovedForAll(account, _msgSender())) { + revert ERC1155MissingApprovalForAll(_msgSender(), account); + } + + _burn(account, id, value); + } + + function burnBatch(address account, uint256[] memory ids, uint256[] memory values) public virtual { + if (account != _msgSender() && !isApprovedForAll(account, _msgSender())) { + revert ERC1155MissingApprovalForAll(_msgSender(), account); + } + + _burnBatch(account, ids, values); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/token/ERC1155/extensions/ERC1155Pausable.sol b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC1155/extensions/ERC1155Pausable.sol new file mode 100644 index 00000000..a0de999f --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC1155/extensions/ERC1155Pausable.sol @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC1155/extensions/ERC1155Pausable.sol) + +pragma solidity ^0.8.20; + +import {ERC1155} from "../ERC1155.sol"; +import {Pausable} from "../../../utils/Pausable.sol"; + +/** + * @dev ERC-1155 token with pausable token transfers, minting and burning. + * + * Useful for scenarios such as preventing trades until the end of an evaluation + * period, or having an emergency switch for freezing all token transfers in the + * event of a large bug. + * + * IMPORTANT: This contract does not include public pause and unpause functions. In + * addition to inheriting this contract, you must define both functions, invoking the + * {Pausable-_pause} and {Pausable-_unpause} internal functions, with appropriate + * access control, e.g. using {AccessControl} or {Ownable}. Not doing so will + * make the contract pause mechanism of the contract unreachable, and thus unusable. + */ +abstract contract ERC1155Pausable is ERC1155, Pausable { + /** + * @dev See {ERC1155-_update}. + * + * Requirements: + * + * - the contract must not be paused. + */ + function _update( + address from, + address to, + uint256[] memory ids, + uint256[] memory values + ) internal virtual override whenNotPaused { + super._update(from, to, ids, values); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/token/ERC1155/extensions/ERC1155Supply.sol b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC1155/extensions/ERC1155Supply.sol new file mode 100644 index 00000000..96d5e606 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC1155/extensions/ERC1155Supply.sol @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC1155/extensions/ERC1155Supply.sol) + +pragma solidity ^0.8.20; + +import {ERC1155} from "../ERC1155.sol"; +import {Arrays} from "../../../utils/Arrays.sol"; + +/** + * @dev Extension of ERC-1155 that adds tracking of total supply per id. + * + * Useful for scenarios where Fungible and Non-fungible tokens have to be + * clearly identified. Note: While a totalSupply of 1 might mean the + * corresponding is an NFT, there is no guarantees that no other token with the + * same id are not going to be minted. + * + * NOTE: This contract implies a global limit of 2**256 - 1 to the number of tokens + * that can be minted. + * + * CAUTION: This extension should not be added in an upgrade to an already deployed contract. + */ +abstract contract ERC1155Supply is ERC1155 { + using Arrays for uint256[]; + + mapping(uint256 id => uint256) private _totalSupply; + uint256 private _totalSupplyAll; + + /** + * @dev Total value of tokens in with a given id. + */ + function totalSupply(uint256 id) public view virtual returns (uint256) { + return _totalSupply[id]; + } + + /** + * @dev Total value of tokens. + */ + function totalSupply() public view virtual returns (uint256) { + return _totalSupplyAll; + } + + /** + * @dev Indicates whether any token exist with a given id, or not. + */ + function exists(uint256 id) public view virtual returns (bool) { + return totalSupply(id) > 0; + } + + /// @inheritdoc ERC1155 + function _update( + address from, + address to, + uint256[] memory ids, + uint256[] memory values + ) internal virtual override { + super._update(from, to, ids, values); + + if (from == address(0)) { + uint256 totalMintValue = 0; + for (uint256 i = 0; i < ids.length; ++i) { + uint256 value = values.unsafeMemoryAccess(i); + // Overflow check required: The rest of the code assumes that totalSupply never overflows + _totalSupply[ids.unsafeMemoryAccess(i)] += value; + totalMintValue += value; + } + // Overflow check required: The rest of the code assumes that totalSupplyAll never overflows + _totalSupplyAll += totalMintValue; + } + + if (to == address(0)) { + uint256 totalBurnValue = 0; + for (uint256 i = 0; i < ids.length; ++i) { + uint256 value = values.unsafeMemoryAccess(i); + + unchecked { + // Overflow not possible: values[i] <= balanceOf(from, ids[i]) <= totalSupply(ids[i]) + _totalSupply[ids.unsafeMemoryAccess(i)] -= value; + // Overflow not possible: sum_i(values[i]) <= sum_i(totalSupply(ids[i])) <= totalSupplyAll + totalBurnValue += value; + } + } + unchecked { + // Overflow not possible: totalBurnValue = sum_i(values[i]) <= sum_i(totalSupply(ids[i])) <= totalSupplyAll + _totalSupplyAll -= totalBurnValue; + } + } + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/token/ERC1155/extensions/ERC1155URIStorage.sol b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC1155/extensions/ERC1155URIStorage.sol new file mode 100644 index 00000000..5abf319d --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC1155/extensions/ERC1155URIStorage.sol @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC1155/extensions/ERC1155URIStorage.sol) + +pragma solidity ^0.8.20; + +import {Strings} from "../../../utils/Strings.sol"; +import {ERC1155} from "../ERC1155.sol"; + +/** + * @dev ERC-1155 token with storage based token URI management. + * Inspired by the {ERC721URIStorage} extension + */ +abstract contract ERC1155URIStorage is ERC1155 { + using Strings for uint256; + + // Optional base URI + string private _baseURI = ""; + + // Optional mapping for token URIs + mapping(uint256 tokenId => string) private _tokenURIs; + + /** + * @dev See {IERC1155MetadataURI-uri}. + * + * This implementation returns the concatenation of the `_baseURI` + * and the token-specific uri if the latter is set + * + * This enables the following behaviors: + * + * - if `_tokenURIs[tokenId]` is set, then the result is the concatenation + * of `_baseURI` and `_tokenURIs[tokenId]` (keep in mind that `_baseURI` + * is empty per default); + * + * - if `_tokenURIs[tokenId]` is NOT set then we fallback to `super.uri()` + * which in most cases will contain `ERC1155._uri`; + * + * - if `_tokenURIs[tokenId]` is NOT set, and if the parents do not have a + * uri value set, then the result is empty. + */ + function uri(uint256 tokenId) public view virtual override returns (string memory) { + string memory tokenURI = _tokenURIs[tokenId]; + + // If token URI is set, concatenate base URI and tokenURI (via string.concat). + return bytes(tokenURI).length > 0 ? string.concat(_baseURI, tokenURI) : super.uri(tokenId); + } + + /** + * @dev Sets `tokenURI` as the tokenURI of `tokenId`. + */ + function _setURI(uint256 tokenId, string memory tokenURI) internal virtual { + _tokenURIs[tokenId] = tokenURI; + emit URI(uri(tokenId), tokenId); + } + + /** + * @dev Sets `baseURI` as the `_baseURI` for all tokens + */ + function _setBaseURI(string memory baseURI) internal virtual { + _baseURI = baseURI; + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/token/ERC1155/extensions/IERC1155MetadataURI.sol b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC1155/extensions/IERC1155MetadataURI.sol new file mode 100644 index 00000000..501d8551 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC1155/extensions/IERC1155MetadataURI.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC1155/extensions/IERC1155MetadataURI.sol) + +pragma solidity >=0.6.2; + +import {IERC1155} from "../IERC1155.sol"; + +/** + * @dev Interface of the optional ERC1155MetadataExtension interface, as defined + * in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[ERC]. + */ +interface IERC1155MetadataURI is IERC1155 { + /** + * @dev Returns the URI for token type `id`. + * + * If the `\{id\}` substring is present in the URI, it must be replaced by + * clients with the actual token type ID. + */ + function uri(uint256 id) external view returns (string memory); +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/token/ERC1155/utils/ERC1155Holder.sol b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC1155/utils/ERC1155Holder.sol new file mode 100644 index 00000000..19d79631 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC1155/utils/ERC1155Holder.sol @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC1155/utils/ERC1155Holder.sol) + +pragma solidity ^0.8.20; + +import {IERC165, ERC165} from "../../../utils/introspection/ERC165.sol"; +import {IERC1155Receiver} from "../IERC1155Receiver.sol"; + +/** + * @dev Simple implementation of `IERC1155Receiver` that will allow a contract to hold ERC-1155 tokens. + * + * IMPORTANT: When inheriting this contract, you must include a way to use the received tokens, otherwise they will be + * stuck. + */ +abstract contract ERC1155Holder is ERC165, IERC1155Receiver { + /// @inheritdoc IERC165 + function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { + return interfaceId == type(IERC1155Receiver).interfaceId || super.supportsInterface(interfaceId); + } + + function onERC1155Received( + address, + address, + uint256, + uint256, + bytes memory + ) public virtual override returns (bytes4) { + return this.onERC1155Received.selector; + } + + function onERC1155BatchReceived( + address, + address, + uint256[] memory, + uint256[] memory, + bytes memory + ) public virtual override returns (bytes4) { + return this.onERC1155BatchReceived.selector; + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/token/ERC1155/utils/ERC1155Utils.sol b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC1155/utils/ERC1155Utils.sol new file mode 100644 index 00000000..03cb0f0b --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC1155/utils/ERC1155Utils.sol @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC1155/utils/ERC1155Utils.sol) + +pragma solidity ^0.8.20; + +import {IERC1155Receiver} from "../IERC1155Receiver.sol"; +import {IERC1155Errors} from "../../../interfaces/draft-IERC6093.sol"; + +/** + * @dev Library that provide common ERC-1155 utility functions. + * + * See https://eips.ethereum.org/EIPS/eip-1155[ERC-1155]. + * + * _Available since v5.1._ + */ +library ERC1155Utils { + /** + * @dev Performs an acceptance check for the provided `operator` by calling {IERC1155Receiver-onERC1155Received} + * on the `to` address. The `operator` is generally the address that initiated the token transfer (i.e. `msg.sender`). + * + * The acceptance call is not executed and treated as a no-op if the target address doesn't contain code (i.e. an EOA). + * Otherwise, the recipient must implement {IERC1155Receiver-onERC1155Received} and return the acceptance magic value to accept + * the transfer. + */ + function checkOnERC1155Received( + address operator, + address from, + address to, + uint256 id, + uint256 value, + bytes memory data + ) internal { + if (to.code.length > 0) { + try IERC1155Receiver(to).onERC1155Received(operator, from, id, value, data) returns (bytes4 response) { + if (response != IERC1155Receiver.onERC1155Received.selector) { + // Tokens rejected + revert IERC1155Errors.ERC1155InvalidReceiver(to); + } + } catch (bytes memory reason) { + if (reason.length == 0) { + // non-IERC1155Receiver implementer + revert IERC1155Errors.ERC1155InvalidReceiver(to); + } else { + assembly ("memory-safe") { + revert(add(reason, 0x20), mload(reason)) + } + } + } + } + } + + /** + * @dev Performs a batch acceptance check for the provided `operator` by calling {IERC1155Receiver-onERC1155BatchReceived} + * on the `to` address. The `operator` is generally the address that initiated the token transfer (i.e. `msg.sender`). + * + * The acceptance call is not executed and treated as a no-op if the target address doesn't contain code (i.e. an EOA). + * Otherwise, the recipient must implement {IERC1155Receiver-onERC1155Received} and return the acceptance magic value to accept + * the transfer. + */ + function checkOnERC1155BatchReceived( + address operator, + address from, + address to, + uint256[] memory ids, + uint256[] memory values, + bytes memory data + ) internal { + if (to.code.length > 0) { + try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, values, data) returns ( + bytes4 response + ) { + if (response != IERC1155Receiver.onERC1155BatchReceived.selector) { + // Tokens rejected + revert IERC1155Errors.ERC1155InvalidReceiver(to); + } + } catch (bytes memory reason) { + if (reason.length == 0) { + // non-IERC1155Receiver implementer + revert IERC1155Errors.ERC1155InvalidReceiver(to); + } else { + assembly ("memory-safe") { + revert(add(reason, 0x20), mload(reason)) + } + } + } + } + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/ERC20.sol b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/ERC20.sol new file mode 100644 index 00000000..886febc5 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/ERC20.sol @@ -0,0 +1,305 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.20; + +import {IERC20} from "./IERC20.sol"; +import {IERC20Metadata} from "./extensions/IERC20Metadata.sol"; +import {Context} from "../../utils/Context.sol"; +import {IERC20Errors} from "../../interfaces/draft-IERC6093.sol"; + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * + * TIP: For a detailed writeup see our guide + * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * The default value of {decimals} is 18. To change this, you should override + * this function so it returns a different value. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC-20 + * applications. + */ +abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors { + mapping(address account => uint256) private _balances; + + mapping(address account => mapping(address spender => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * Both values are immutable: they can only be set once during construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the default value returned by this function, unless + * it's overridden. + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual returns (uint8) { + return 18; + } + + /// @inheritdoc IERC20 + function totalSupply() public view virtual returns (uint256) { + return _totalSupply; + } + + /// @inheritdoc IERC20 + function balanceOf(address account) public view virtual returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `to` cannot be the zero address. + * - the caller must have a balance of at least `value`. + */ + function transfer(address to, uint256 value) public virtual returns (bool) { + address owner = _msgSender(); + _transfer(owner, to, value); + return true; + } + + /// @inheritdoc IERC20 + function allowance(address owner, address spender) public view virtual returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * NOTE: If `value` is the maximum `uint256`, the allowance is not updated on + * `transferFrom`. This is semantically equivalent to an infinite approval. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 value) public virtual returns (bool) { + address owner = _msgSender(); + _approve(owner, spender, value); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Skips emitting an {Approval} event indicating an allowance update. This is not + * required by the ERC. See {xref-ERC20-_approve-address-address-uint256-bool-}[_approve]. + * + * NOTE: Does not update the allowance if the current allowance + * is the maximum `uint256`. + * + * Requirements: + * + * - `from` and `to` cannot be the zero address. + * - `from` must have a balance of at least `value`. + * - the caller must have allowance for ``from``'s tokens of at least + * `value`. + */ + function transferFrom(address from, address to, uint256 value) public virtual returns (bool) { + address spender = _msgSender(); + _spendAllowance(from, spender, value); + _transfer(from, to, value); + return true; + } + + /** + * @dev Moves a `value` amount of tokens from `from` to `to`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * NOTE: This function is not virtual, {_update} should be overridden instead. + */ + function _transfer(address from, address to, uint256 value) internal { + if (from == address(0)) { + revert ERC20InvalidSender(address(0)); + } + if (to == address(0)) { + revert ERC20InvalidReceiver(address(0)); + } + _update(from, to, value); + } + + /** + * @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from` + * (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding + * this function. + * + * Emits a {Transfer} event. + */ + function _update(address from, address to, uint256 value) internal virtual { + if (from == address(0)) { + // Overflow check required: The rest of the code assumes that totalSupply never overflows + _totalSupply += value; + } else { + uint256 fromBalance = _balances[from]; + if (fromBalance < value) { + revert ERC20InsufficientBalance(from, fromBalance, value); + } + unchecked { + // Overflow not possible: value <= fromBalance <= totalSupply. + _balances[from] = fromBalance - value; + } + } + + if (to == address(0)) { + unchecked { + // Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply. + _totalSupply -= value; + } + } else { + unchecked { + // Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256. + _balances[to] += value; + } + } + + emit Transfer(from, to, value); + } + + /** + * @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0). + * Relies on the `_update` mechanism + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * NOTE: This function is not virtual, {_update} should be overridden instead. + */ + function _mint(address account, uint256 value) internal { + if (account == address(0)) { + revert ERC20InvalidReceiver(address(0)); + } + _update(address(0), account, value); + } + + /** + * @dev Destroys a `value` amount of tokens from `account`, lowering the total supply. + * Relies on the `_update` mechanism. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * NOTE: This function is not virtual, {_update} should be overridden instead + */ + function _burn(address account, uint256 value) internal { + if (account == address(0)) { + revert ERC20InvalidSender(address(0)); + } + _update(account, address(0), value); + } + + /** + * @dev Sets `value` as the allowance of `spender` over the `owner`'s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + * + * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument. + */ + function _approve(address owner, address spender, uint256 value) internal { + _approve(owner, spender, value, true); + } + + /** + * @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event. + * + * By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by + * `_spendAllowance` during the `transferFrom` operation set the flag to false. This saves gas by not emitting any + * `Approval` event during `transferFrom` operations. + * + * Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to + * true using the following override: + * + * ```solidity + * function _approve(address owner, address spender, uint256 value, bool) internal virtual override { + * super._approve(owner, spender, value, true); + * } + * ``` + * + * Requirements are the same as {_approve}. + */ + function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual { + if (owner == address(0)) { + revert ERC20InvalidApprover(address(0)); + } + if (spender == address(0)) { + revert ERC20InvalidSpender(address(0)); + } + _allowances[owner][spender] = value; + if (emitEvent) { + emit Approval(owner, spender, value); + } + } + + /** + * @dev Updates `owner`'s allowance for `spender` based on spent `value`. + * + * Does not update the allowance value in case of infinite allowance. + * Revert if not enough allowance is available. + * + * Does not emit an {Approval} event. + */ + function _spendAllowance(address owner, address spender, uint256 value) internal virtual { + uint256 currentAllowance = allowance(owner, spender); + if (currentAllowance < type(uint256).max) { + if (currentAllowance < value) { + revert ERC20InsufficientAllowance(spender, currentAllowance, value); + } + unchecked { + _approve(owner, spender, currentAllowance - value, false); + } + } + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/IERC20.sol b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/IERC20.sol new file mode 100644 index 00000000..b493743a --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/IERC20.sol @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/IERC20.sol) + +pragma solidity >=0.4.16; + +/** + * @dev Interface of the ERC-20 standard as defined in the ERC. + */ +interface IERC20 { + /** + * @dev Emitted when `value` tokens are moved from one account (`from`) to + * another (`to`). + * + * Note that `value` may be zero. + */ + event Transfer(address indexed from, address indexed to, uint256 value); + + /** + * @dev Emitted when the allowance of a `spender` for an `owner` is set by + * a call to {approve}. `value` is the new allowance. + */ + event Approval(address indexed owner, address indexed spender, uint256 value); + + /** + * @dev Returns the value of tokens in existence. + */ + function totalSupply() external view returns (uint256); + + /** + * @dev Returns the value of tokens owned by `account`. + */ + function balanceOf(address account) external view returns (uint256); + + /** + * @dev Moves a `value` amount of tokens from the caller's account to `to`. + * + * Returns a boolean value indicating whether the operation succeeded. + * + * Emits a {Transfer} event. + */ + function transfer(address to, uint256 value) external returns (bool); + + /** + * @dev Returns the remaining number of tokens that `spender` will be + * allowed to spend on behalf of `owner` through {transferFrom}. This is + * zero by default. + * + * This value changes when {approve} or {transferFrom} are called. + */ + function allowance(address owner, address spender) external view returns (uint256); + + /** + * @dev Sets a `value` amount of tokens as the allowance of `spender` over the + * caller's tokens. + * + * Returns a boolean value indicating whether the operation succeeded. + * + * IMPORTANT: Beware that changing an allowance with this method brings the risk + * that someone may use both the old and the new allowance by unfortunate + * transaction ordering. One possible solution to mitigate this race + * condition is to first reduce the spender's allowance to 0 and set the + * desired value afterwards: + * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 + * + * Emits an {Approval} event. + */ + function approve(address spender, uint256 value) external returns (bool); + + /** + * @dev Moves a `value` amount of tokens from `from` to `to` using the + * allowance mechanism. `value` is then deducted from the caller's + * allowance. + * + * Returns a boolean value indicating whether the operation succeeded. + * + * Emits a {Transfer} event. + */ + function transferFrom(address from, address to, uint256 value) external returns (bool); +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/extensions/ERC1363.sol b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/extensions/ERC1363.sol new file mode 100644 index 00000000..3b3dbba7 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/extensions/ERC1363.sol @@ -0,0 +1,135 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/extensions/ERC1363.sol) + +pragma solidity ^0.8.20; + +import {ERC20} from "../ERC20.sol"; +import {IERC165, ERC165} from "../../../utils/introspection/ERC165.sol"; +import {IERC1363} from "../../../interfaces/IERC1363.sol"; +import {ERC1363Utils} from "../utils/ERC1363Utils.sol"; + +/** + * @title ERC1363 + * @dev Extension of {ERC20} tokens that adds support for code execution after transfers and approvals + * on recipient contracts. Calls after transfers are enabled through the {ERC1363-transferAndCall} and + * {ERC1363-transferFromAndCall} methods while calls after approvals can be made with {ERC1363-approveAndCall} + * + * _Available since v5.1._ + */ +abstract contract ERC1363 is ERC20, ERC165, IERC1363 { + /** + * @dev Indicates a failure within the {transfer} part of a transferAndCall operation. + * @param receiver Address to which tokens are being transferred. + * @param value Amount of tokens to be transferred. + */ + error ERC1363TransferFailed(address receiver, uint256 value); + + /** + * @dev Indicates a failure within the {transferFrom} part of a transferFromAndCall operation. + * @param sender Address from which to send tokens. + * @param receiver Address to which tokens are being transferred. + * @param value Amount of tokens to be transferred. + */ + error ERC1363TransferFromFailed(address sender, address receiver, uint256 value); + + /** + * @dev Indicates a failure within the {approve} part of a approveAndCall operation. + * @param spender Address which will spend the funds. + * @param value Amount of tokens to be spent. + */ + error ERC1363ApproveFailed(address spender, uint256 value); + + /// @inheritdoc IERC165 + function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { + return interfaceId == type(IERC1363).interfaceId || super.supportsInterface(interfaceId); + } + + /** + * @dev Moves a `value` amount of tokens from the caller's account to `to` + * and then calls {IERC1363Receiver-onTransferReceived} on `to`. Returns a flag that indicates + * if the call succeeded. + * + * Requirements: + * + * - The target has code (i.e. is a contract). + * - The target `to` must implement the {IERC1363Receiver} interface. + * - The target must return the {IERC1363Receiver-onTransferReceived} selector to accept the transfer. + * - The internal {transfer} must succeed (returned `true`). + */ + function transferAndCall(address to, uint256 value) public returns (bool) { + return transferAndCall(to, value, ""); + } + + /** + * @dev Variant of {transferAndCall} that accepts an additional `data` parameter with + * no specified format. + */ + function transferAndCall(address to, uint256 value, bytes memory data) public virtual returns (bool) { + if (!transfer(to, value)) { + revert ERC1363TransferFailed(to, value); + } + ERC1363Utils.checkOnERC1363TransferReceived(_msgSender(), _msgSender(), to, value, data); + return true; + } + + /** + * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism + * and then calls {IERC1363Receiver-onTransferReceived} on `to`. Returns a flag that indicates + * if the call succeeded. + * + * Requirements: + * + * - The target has code (i.e. is a contract). + * - The target `to` must implement the {IERC1363Receiver} interface. + * - The target must return the {IERC1363Receiver-onTransferReceived} selector to accept the transfer. + * - The internal {transferFrom} must succeed (returned `true`). + */ + function transferFromAndCall(address from, address to, uint256 value) public returns (bool) { + return transferFromAndCall(from, to, value, ""); + } + + /** + * @dev Variant of {transferFromAndCall} that accepts an additional `data` parameter with + * no specified format. + */ + function transferFromAndCall( + address from, + address to, + uint256 value, + bytes memory data + ) public virtual returns (bool) { + if (!transferFrom(from, to, value)) { + revert ERC1363TransferFromFailed(from, to, value); + } + ERC1363Utils.checkOnERC1363TransferReceived(_msgSender(), from, to, value, data); + return true; + } + + /** + * @dev Sets a `value` amount of tokens as the allowance of `spender` over the + * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`. + * Returns a flag that indicates if the call succeeded. + * + * Requirements: + * + * - The target has code (i.e. is a contract). + * - The target `spender` must implement the {IERC1363Spender} interface. + * - The target must return the {IERC1363Spender-onApprovalReceived} selector to accept the approval. + * - The internal {approve} must succeed (returned `true`). + */ + function approveAndCall(address spender, uint256 value) public returns (bool) { + return approveAndCall(spender, value, ""); + } + + /** + * @dev Variant of {approveAndCall} that accepts an additional `data` parameter with + * no specified format. + */ + function approveAndCall(address spender, uint256 value, bytes memory data) public virtual returns (bool) { + if (!approve(spender, value)) { + revert ERC1363ApproveFailed(spender, value); + } + ERC1363Utils.checkOnERC1363ApprovalReceived(_msgSender(), spender, value, data); + return true; + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/extensions/ERC20Burnable.sol b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/extensions/ERC20Burnable.sol new file mode 100644 index 00000000..4d482d8e --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/extensions/ERC20Burnable.sol @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/ERC20Burnable.sol) + +pragma solidity ^0.8.20; + +import {ERC20} from "../ERC20.sol"; +import {Context} from "../../../utils/Context.sol"; + +/** + * @dev Extension of {ERC20} that allows token holders to destroy both their own + * tokens and those that they have an allowance for, in a way that can be + * recognized off-chain (via event analysis). + */ +abstract contract ERC20Burnable is Context, ERC20 { + /** + * @dev Destroys a `value` amount of tokens from the caller. + * + * See {ERC20-_burn}. + */ + function burn(uint256 value) public virtual { + _burn(_msgSender(), value); + } + + /** + * @dev Destroys a `value` amount of tokens from `account`, deducting from + * the caller's allowance. + * + * See {ERC20-_burn} and {ERC20-allowance}. + * + * Requirements: + * + * - the caller must have allowance for ``accounts``'s tokens of at least + * `value`. + */ + function burnFrom(address account, uint256 value) public virtual { + _spendAllowance(account, _msgSender(), value); + _burn(account, value); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/extensions/ERC20Capped.sol b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/extensions/ERC20Capped.sol new file mode 100644 index 00000000..c6d09003 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/extensions/ERC20Capped.sol @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/extensions/ERC20Capped.sol) + +pragma solidity ^0.8.20; + +import {ERC20} from "../ERC20.sol"; + +/** + * @dev Extension of {ERC20} that adds a cap to the supply of tokens. + */ +abstract contract ERC20Capped is ERC20 { + uint256 private immutable _cap; + + /** + * @dev Total supply cap has been exceeded. + */ + error ERC20ExceededCap(uint256 increasedSupply, uint256 cap); + + /** + * @dev The supplied cap is not a valid cap. + */ + error ERC20InvalidCap(uint256 cap); + + /** + * @dev Sets the value of the `cap`. This value is immutable, it can only be + * set once during construction. + */ + constructor(uint256 cap_) { + if (cap_ == 0) { + revert ERC20InvalidCap(0); + } + _cap = cap_; + } + + /** + * @dev Returns the cap on the token's total supply. + */ + function cap() public view virtual returns (uint256) { + return _cap; + } + + /// @inheritdoc ERC20 + function _update(address from, address to, uint256 value) internal virtual override { + super._update(from, to, value); + + if (from == address(0)) { + uint256 maxSupply = cap(); + uint256 supply = totalSupply(); + if (supply > maxSupply) { + revert ERC20ExceededCap(supply, maxSupply); + } + } + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/extensions/ERC20FlashMint.sol b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/extensions/ERC20FlashMint.sol new file mode 100644 index 00000000..4d3a31f6 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/extensions/ERC20FlashMint.sol @@ -0,0 +1,134 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/ERC20FlashMint.sol) + +pragma solidity ^0.8.20; + +import {IERC3156FlashBorrower} from "../../../interfaces/IERC3156FlashBorrower.sol"; +import {IERC3156FlashLender} from "../../../interfaces/IERC3156FlashLender.sol"; +import {ERC20} from "../ERC20.sol"; + +/** + * @dev Implementation of the ERC-3156 Flash loans extension, as defined in + * https://eips.ethereum.org/EIPS/eip-3156[ERC-3156]. + * + * Adds the {flashLoan} method, which provides flash loan support at the token + * level. By default there is no fee, but this can be changed by overriding {flashFee}. + * + * NOTE: When this extension is used along with the {ERC20Capped} or {ERC20Votes} extensions, + * {maxFlashLoan} will not correctly reflect the maximum that can be flash minted. We recommend + * overriding {maxFlashLoan} so that it correctly reflects the supply cap. + */ +abstract contract ERC20FlashMint is ERC20, IERC3156FlashLender { + bytes32 private constant RETURN_VALUE = keccak256("ERC3156FlashBorrower.onFlashLoan"); + + /** + * @dev The loan token is not valid. + */ + error ERC3156UnsupportedToken(address token); + + /** + * @dev The requested loan exceeds the max loan value for `token`. + */ + error ERC3156ExceededMaxLoan(uint256 maxLoan); + + /** + * @dev The receiver of a flashloan is not a valid {IERC3156FlashBorrower-onFlashLoan} implementer. + */ + error ERC3156InvalidReceiver(address receiver); + + /** + * @dev Returns the maximum amount of tokens available for loan. + * @param token The address of the token that is requested. + * @return The amount of token that can be loaned. + * + * NOTE: This function does not consider any form of supply cap, so in case + * it's used in a token with a cap like {ERC20Capped}, make sure to override this + * function to integrate the cap instead of `type(uint256).max`. + */ + function maxFlashLoan(address token) public view virtual returns (uint256) { + return token == address(this) ? type(uint256).max - totalSupply() : 0; + } + + /** + * @dev Returns the fee applied when doing flash loans. This function calls + * the {_flashFee} function which returns the fee applied when doing flash + * loans. + * @param token The token to be flash loaned. + * @param value The amount of tokens to be loaned. + * @return The fees applied to the corresponding flash loan. + */ + function flashFee(address token, uint256 value) public view virtual returns (uint256) { + if (token != address(this)) { + revert ERC3156UnsupportedToken(token); + } + return _flashFee(token, value); + } + + /** + * @dev Returns the fee applied when doing flash loans. By default this + * implementation has 0 fees. This function can be overloaded to make + * the flash loan mechanism deflationary. + * @param token The token to be flash loaned. + * @param value The amount of tokens to be loaned. + * @return The fees applied to the corresponding flash loan. + */ + function _flashFee(address token, uint256 value) internal view virtual returns (uint256) { + // silence warning about unused variable without the addition of bytecode. + token; + value; + return 0; + } + + /** + * @dev Returns the receiver address of the flash fee. By default this + * implementation returns the address(0) which means the fee amount will be burnt. + * This function can be overloaded to change the fee receiver. + * @return The address for which the flash fee will be sent to. + */ + function _flashFeeReceiver() internal view virtual returns (address) { + return address(0); + } + + /** + * @dev Performs a flash loan. New tokens are minted and sent to the + * `receiver`, who is required to implement the {IERC3156FlashBorrower} + * interface. By the end of the flash loan, the receiver is expected to own + * value + fee tokens and have them approved back to the token contract itself so + * they can be burned. + * @param receiver The receiver of the flash loan. Should implement the + * {IERC3156FlashBorrower-onFlashLoan} interface. + * @param token The token to be flash loaned. Only `address(this)` is + * supported. + * @param value The amount of tokens to be loaned. + * @param data An arbitrary datafield that is passed to the receiver. + * @return `true` if the flash loan was successful. + */ + // This function can reenter, but it doesn't pose a risk because it always preserves the property that the amount + // minted at the beginning is always recovered and burned at the end, or else the entire function will revert. + // slither-disable-next-line reentrancy-no-eth + function flashLoan( + IERC3156FlashBorrower receiver, + address token, + uint256 value, + bytes calldata data + ) public virtual returns (bool) { + uint256 maxLoan = maxFlashLoan(token); + if (value > maxLoan) { + revert ERC3156ExceededMaxLoan(maxLoan); + } + uint256 fee = flashFee(token, value); + _mint(address(receiver), value); + if (receiver.onFlashLoan(_msgSender(), token, value, fee, data) != RETURN_VALUE) { + revert ERC3156InvalidReceiver(address(receiver)); + } + address flashFeeReceiver = _flashFeeReceiver(); + _spendAllowance(address(receiver), address(this), value + fee); + if (fee == 0 || flashFeeReceiver == address(0)) { + _burn(address(receiver), value + fee); + } else { + _burn(address(receiver), value); + _transfer(address(receiver), flashFeeReceiver, fee); + } + return true; + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/extensions/ERC20Pausable.sol b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/extensions/ERC20Pausable.sol new file mode 100644 index 00000000..2f6d86c4 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/extensions/ERC20Pausable.sol @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/ERC20Pausable.sol) + +pragma solidity ^0.8.20; + +import {ERC20} from "../ERC20.sol"; +import {Pausable} from "../../../utils/Pausable.sol"; + +/** + * @dev ERC-20 token with pausable token transfers, minting and burning. + * + * Useful for scenarios such as preventing trades until the end of an evaluation + * period, or having an emergency switch for freezing all token transfers in the + * event of a large bug. + * + * IMPORTANT: This contract does not include public pause and unpause functions. In + * addition to inheriting this contract, you must define both functions, invoking the + * {Pausable-_pause} and {Pausable-_unpause} internal functions, with appropriate + * access control, e.g. using {AccessControl} or {Ownable}. Not doing so will + * make the contract pause mechanism of the contract unreachable, and thus unusable. + */ +abstract contract ERC20Pausable is ERC20, Pausable { + /** + * @dev See {ERC20-_update}. + * + * Requirements: + * + * - the contract must not be paused. + */ + function _update(address from, address to, uint256 value) internal virtual override whenNotPaused { + super._update(from, to, value); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/extensions/ERC20Permit.sol b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/extensions/ERC20Permit.sol new file mode 100644 index 00000000..7efa9ed6 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/extensions/ERC20Permit.sol @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/extensions/ERC20Permit.sol) + +pragma solidity ^0.8.20; + +import {IERC20Permit} from "./IERC20Permit.sol"; +import {ERC20} from "../ERC20.sol"; +import {ECDSA} from "../../../utils/cryptography/ECDSA.sol"; +import {EIP712} from "../../../utils/cryptography/EIP712.sol"; +import {Nonces} from "../../../utils/Nonces.sol"; + +/** + * @dev Implementation of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in + * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612]. + * + * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by + * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't + * need to send a transaction, and thus is not required to hold Ether at all. + */ +abstract contract ERC20Permit is ERC20, IERC20Permit, EIP712, Nonces { + bytes32 private constant PERMIT_TYPEHASH = + keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"); + + /** + * @dev Permit deadline has expired. + */ + error ERC2612ExpiredSignature(uint256 deadline); + + /** + * @dev Mismatched signature. + */ + error ERC2612InvalidSigner(address signer, address owner); + + /** + * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `"1"`. + * + * It's a good idea to use the same `name` that is defined as the ERC-20 token name. + */ + constructor(string memory name) EIP712(name, "1") {} + + /// @inheritdoc IERC20Permit + function permit( + address owner, + address spender, + uint256 value, + uint256 deadline, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual { + if (block.timestamp > deadline) { + revert ERC2612ExpiredSignature(deadline); + } + + bytes32 structHash = keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, _useNonce(owner), deadline)); + + bytes32 hash = _hashTypedDataV4(structHash); + + address signer = ECDSA.recover(hash, v, r, s); + if (signer != owner) { + revert ERC2612InvalidSigner(signer, owner); + } + + _approve(owner, spender, value); + } + + /// @inheritdoc IERC20Permit + function nonces(address owner) public view virtual override(IERC20Permit, Nonces) returns (uint256) { + return super.nonces(owner); + } + + /// @inheritdoc IERC20Permit + // solhint-disable-next-line func-name-mixedcase + function DOMAIN_SEPARATOR() external view virtual returns (bytes32) { + return _domainSeparatorV4(); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/extensions/ERC20Votes.sol b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/extensions/ERC20Votes.sol new file mode 100644 index 00000000..c15e7f56 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/extensions/ERC20Votes.sol @@ -0,0 +1,83 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.20; + +import {ERC20} from "../ERC20.sol"; +import {Votes} from "../../../governance/utils/Votes.sol"; +import {Checkpoints} from "../../../utils/structs/Checkpoints.sol"; + +/** + * @dev Extension of ERC-20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^208^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: This contract does not provide interface compatibility with Compound's COMP token. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {Votes-delegate} function directly, or by providing a signature to be used with {Votes-delegateBySig}. Voting + * power can be queried through the public accessors {Votes-getVotes} and {Votes-getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + */ +abstract contract ERC20Votes is ERC20, Votes { + /** + * @dev Total supply cap has been exceeded, introducing a risk of votes overflowing. + */ + error ERC20ExceededSafeSupply(uint256 increasedSupply, uint256 cap); + + /** + * @dev Maximum token supply. Defaults to `type(uint208).max` (2^208^ - 1). + * + * This maximum is enforced in {_update}. It limits the total supply of the token, which is otherwise a uint256, + * so that checkpoints can be stored in the Trace208 structure used by {Votes}. Increasing this value will not + * remove the underlying limitation, and will cause {_update} to fail because of a math overflow in + * {Votes-_transferVotingUnits}. An override could be used to further restrict the total supply (to a lower value) if + * additional logic requires it. When resolving override conflicts on this function, the minimum should be + * returned. + */ + function _maxSupply() internal view virtual returns (uint256) { + return type(uint208).max; + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {IVotes-DelegateVotesChanged} event. + */ + function _update(address from, address to, uint256 value) internal virtual override { + super._update(from, to, value); + if (from == address(0)) { + uint256 supply = totalSupply(); + uint256 cap = _maxSupply(); + if (supply > cap) { + revert ERC20ExceededSafeSupply(supply, cap); + } + } + _transferVotingUnits(from, to, value); + } + + /** + * @dev Returns the voting units of an `account`. + * + * WARNING: Overriding this function may compromise the internal vote accounting. + * `ERC20Votes` assumes tokens map to voting units 1:1 and this is not easy to change. + */ + function _getVotingUnits(address account) internal view virtual override returns (uint256) { + return balanceOf(account); + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return _numCheckpoints(account); + } + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoints.Checkpoint208 memory) { + return _checkpoints(account, pos); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/extensions/ERC20Wrapper.sol b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/extensions/ERC20Wrapper.sol new file mode 100644 index 00000000..8916d1ab --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/extensions/ERC20Wrapper.sol @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/extensions/ERC20Wrapper.sol) + +pragma solidity ^0.8.20; + +import {IERC20, IERC20Metadata, ERC20} from "../ERC20.sol"; +import {SafeERC20} from "../utils/SafeERC20.sol"; + +/** + * @dev Extension of the ERC-20 token contract to support token wrapping. + * + * Users can deposit and withdraw "underlying tokens" and receive a matching number of "wrapped tokens". This is useful + * in conjunction with other modules. For example, combining this wrapping mechanism with {ERC20Votes} will allow the + * wrapping of an existing "basic" ERC-20 into a governance token. + * + * WARNING: Any mechanism in which the underlying token changes the {balanceOf} of an account without an explicit transfer + * may desynchronize this contract's supply and its underlying balance. Please exercise caution when wrapping tokens that + * may undercollateralize the wrapper (i.e. wrapper's total supply is higher than its underlying balance). See {_recover} + * for recovering value accrued to the wrapper. + */ +abstract contract ERC20Wrapper is ERC20 { + IERC20 private immutable _underlying; + + /** + * @dev The underlying token couldn't be wrapped. + */ + error ERC20InvalidUnderlying(address token); + + constructor(IERC20 underlyingToken) { + if (underlyingToken == this) { + revert ERC20InvalidUnderlying(address(this)); + } + _underlying = underlyingToken; + } + + /// @inheritdoc IERC20Metadata + function decimals() public view virtual override returns (uint8) { + try IERC20Metadata(address(_underlying)).decimals() returns (uint8 value) { + return value; + } catch { + return super.decimals(); + } + } + + /** + * @dev Returns the address of the underlying ERC-20 token that is being wrapped. + */ + function underlying() public view returns (IERC20) { + return _underlying; + } + + /** + * @dev Allow a user to deposit underlying tokens and mint the corresponding number of wrapped tokens. + */ + function depositFor(address account, uint256 value) public virtual returns (bool) { + address sender = _msgSender(); + if (sender == address(this)) { + revert ERC20InvalidSender(address(this)); + } + if (account == address(this)) { + revert ERC20InvalidReceiver(account); + } + SafeERC20.safeTransferFrom(_underlying, sender, address(this), value); + _mint(account, value); + return true; + } + + /** + * @dev Allow a user to burn a number of wrapped tokens and withdraw the corresponding number of underlying tokens. + */ + function withdrawTo(address account, uint256 value) public virtual returns (bool) { + if (account == address(this)) { + revert ERC20InvalidReceiver(account); + } + _burn(_msgSender(), value); + SafeERC20.safeTransfer(_underlying, account, value); + return true; + } + + /** + * @dev Mint wrapped token to cover any underlyingTokens that would have been transferred by mistake or acquired from + * rebasing mechanisms. Internal function that can be exposed with access control if desired. + */ + function _recover(address account) internal virtual returns (uint256) { + uint256 value = _underlying.balanceOf(address(this)) - totalSupply(); + _mint(account, value); + return value; + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/extensions/ERC4626.sol b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/extensions/ERC4626.sol new file mode 100644 index 00000000..fd8231ac --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/extensions/ERC4626.sol @@ -0,0 +1,282 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/extensions/ERC4626.sol) + +pragma solidity ^0.8.20; + +import {IERC20, IERC20Metadata, ERC20} from "../ERC20.sol"; +import {SafeERC20} from "../utils/SafeERC20.sol"; +import {IERC4626} from "../../../interfaces/IERC4626.sol"; +import {Math} from "../../../utils/math/Math.sol"; + +/** + * @dev Implementation of the ERC-4626 "Tokenized Vault Standard" as defined in + * https://eips.ethereum.org/EIPS/eip-4626[ERC-4626]. + * + * This extension allows the minting and burning of "shares" (represented using the ERC-20 inheritance) in exchange for + * underlying "assets" through standardized {deposit}, {mint}, {redeem} and {burn} workflows. This contract extends + * the ERC-20 standard. Any additional extensions included along it would affect the "shares" token represented by this + * contract and not the "assets" token which is an independent contract. + * + * [CAUTION] + * ==== + * In empty (or nearly empty) ERC-4626 vaults, deposits are at high risk of being stolen through frontrunning + * with a "donation" to the vault that inflates the price of a share. This is variously known as a donation or inflation + * attack and is essentially a problem of slippage. Vault deployers can protect against this attack by making an initial + * deposit of a non-trivial amount of the asset, such that price manipulation becomes infeasible. Withdrawals may + * similarly be affected by slippage. Users can protect against this attack as well as unexpected slippage in general by + * verifying the amount received is as expected, using a wrapper that performs these checks such as + * https://github.com/fei-protocol/ERC4626#erc4626router-and-base[ERC4626Router]. + * + * Since v4.9, this implementation introduces configurable virtual assets and shares to help developers mitigate that risk. + * The `_decimalsOffset()` corresponds to an offset in the decimal representation between the underlying asset's decimals + * and the vault decimals. This offset also determines the rate of virtual shares to virtual assets in the vault, which + * itself determines the initial exchange rate. While not fully preventing the attack, analysis shows that the default + * offset (0) makes it non-profitable even if an attacker is able to capture value from multiple user deposits, as a result + * of the value being captured by the virtual shares (out of the attacker's donation) matching the attacker's expected gains. + * With a larger offset, the attack becomes orders of magnitude more expensive than it is profitable. More details about the + * underlying math can be found xref:ROOT:erc4626.adoc#inflation-attack[here]. + * + * The drawback of this approach is that the virtual shares do capture (a very small) part of the value being accrued + * to the vault. Also, if the vault experiences losses, the users try to exit the vault, the virtual shares and assets + * will cause the first user to exit to experience reduced losses in detriment to the last users that will experience + * bigger losses. Developers willing to revert back to the pre-v4.9 behavior just need to override the + * `_convertToShares` and `_convertToAssets` functions. + * + * To learn more, check out our xref:ROOT:erc4626.adoc[ERC-4626 guide]. + * ==== + */ +abstract contract ERC4626 is ERC20, IERC4626 { + using Math for uint256; + + IERC20 private immutable _asset; + uint8 private immutable _underlyingDecimals; + + /** + * @dev Attempted to deposit more assets than the max amount for `receiver`. + */ + error ERC4626ExceededMaxDeposit(address receiver, uint256 assets, uint256 max); + + /** + * @dev Attempted to mint more shares than the max amount for `receiver`. + */ + error ERC4626ExceededMaxMint(address receiver, uint256 shares, uint256 max); + + /** + * @dev Attempted to withdraw more assets than the max amount for `receiver`. + */ + error ERC4626ExceededMaxWithdraw(address owner, uint256 assets, uint256 max); + + /** + * @dev Attempted to redeem more shares than the max amount for `receiver`. + */ + error ERC4626ExceededMaxRedeem(address owner, uint256 shares, uint256 max); + + /** + * @dev Set the underlying asset contract. This must be an ERC20-compatible contract (ERC-20 or ERC-777). + */ + constructor(IERC20 asset_) { + (bool success, uint8 assetDecimals) = _tryGetAssetDecimals(asset_); + _underlyingDecimals = success ? assetDecimals : 18; + _asset = asset_; + } + + /** + * @dev Attempts to fetch the asset decimals. A return value of false indicates that the attempt failed in some way. + */ + function _tryGetAssetDecimals(IERC20 asset_) private view returns (bool ok, uint8 assetDecimals) { + (bool success, bytes memory encodedDecimals) = address(asset_).staticcall( + abi.encodeCall(IERC20Metadata.decimals, ()) + ); + if (success && encodedDecimals.length >= 32) { + uint256 returnedDecimals = abi.decode(encodedDecimals, (uint256)); + if (returnedDecimals <= type(uint8).max) { + return (true, uint8(returnedDecimals)); + } + } + return (false, 0); + } + + /** + * @dev Decimals are computed by adding the decimal offset on top of the underlying asset's decimals. This + * "original" value is cached during construction of the vault contract. If this read operation fails (e.g., the + * asset has not been created yet), a default of 18 is used to represent the underlying asset's decimals. + * + * See {IERC20Metadata-decimals}. + */ + function decimals() public view virtual override(IERC20Metadata, ERC20) returns (uint8) { + return _underlyingDecimals + _decimalsOffset(); + } + + /// @inheritdoc IERC4626 + function asset() public view virtual returns (address) { + return address(_asset); + } + + /// @inheritdoc IERC4626 + function totalAssets() public view virtual returns (uint256) { + return IERC20(asset()).balanceOf(address(this)); + } + + /// @inheritdoc IERC4626 + function convertToShares(uint256 assets) public view virtual returns (uint256) { + return _convertToShares(assets, Math.Rounding.Floor); + } + + /// @inheritdoc IERC4626 + function convertToAssets(uint256 shares) public view virtual returns (uint256) { + return _convertToAssets(shares, Math.Rounding.Floor); + } + + /// @inheritdoc IERC4626 + function maxDeposit(address) public view virtual returns (uint256) { + return type(uint256).max; + } + + /// @inheritdoc IERC4626 + function maxMint(address) public view virtual returns (uint256) { + return type(uint256).max; + } + + /// @inheritdoc IERC4626 + function maxWithdraw(address owner) public view virtual returns (uint256) { + return _convertToAssets(balanceOf(owner), Math.Rounding.Floor); + } + + /// @inheritdoc IERC4626 + function maxRedeem(address owner) public view virtual returns (uint256) { + return balanceOf(owner); + } + + /// @inheritdoc IERC4626 + function previewDeposit(uint256 assets) public view virtual returns (uint256) { + return _convertToShares(assets, Math.Rounding.Floor); + } + + /// @inheritdoc IERC4626 + function previewMint(uint256 shares) public view virtual returns (uint256) { + return _convertToAssets(shares, Math.Rounding.Ceil); + } + + /// @inheritdoc IERC4626 + function previewWithdraw(uint256 assets) public view virtual returns (uint256) { + return _convertToShares(assets, Math.Rounding.Ceil); + } + + /// @inheritdoc IERC4626 + function previewRedeem(uint256 shares) public view virtual returns (uint256) { + return _convertToAssets(shares, Math.Rounding.Floor); + } + + /// @inheritdoc IERC4626 + function deposit(uint256 assets, address receiver) public virtual returns (uint256) { + uint256 maxAssets = maxDeposit(receiver); + if (assets > maxAssets) { + revert ERC4626ExceededMaxDeposit(receiver, assets, maxAssets); + } + + uint256 shares = previewDeposit(assets); + _deposit(_msgSender(), receiver, assets, shares); + + return shares; + } + + /// @inheritdoc IERC4626 + function mint(uint256 shares, address receiver) public virtual returns (uint256) { + uint256 maxShares = maxMint(receiver); + if (shares > maxShares) { + revert ERC4626ExceededMaxMint(receiver, shares, maxShares); + } + + uint256 assets = previewMint(shares); + _deposit(_msgSender(), receiver, assets, shares); + + return assets; + } + + /// @inheritdoc IERC4626 + function withdraw(uint256 assets, address receiver, address owner) public virtual returns (uint256) { + uint256 maxAssets = maxWithdraw(owner); + if (assets > maxAssets) { + revert ERC4626ExceededMaxWithdraw(owner, assets, maxAssets); + } + + uint256 shares = previewWithdraw(assets); + _withdraw(_msgSender(), receiver, owner, assets, shares); + + return shares; + } + + /// @inheritdoc IERC4626 + function redeem(uint256 shares, address receiver, address owner) public virtual returns (uint256) { + uint256 maxShares = maxRedeem(owner); + if (shares > maxShares) { + revert ERC4626ExceededMaxRedeem(owner, shares, maxShares); + } + + uint256 assets = previewRedeem(shares); + _withdraw(_msgSender(), receiver, owner, assets, shares); + + return assets; + } + + /** + * @dev Internal conversion function (from assets to shares) with support for rounding direction. + */ + function _convertToShares(uint256 assets, Math.Rounding rounding) internal view virtual returns (uint256) { + return assets.mulDiv(totalSupply() + 10 ** _decimalsOffset(), totalAssets() + 1, rounding); + } + + /** + * @dev Internal conversion function (from shares to assets) with support for rounding direction. + */ + function _convertToAssets(uint256 shares, Math.Rounding rounding) internal view virtual returns (uint256) { + return shares.mulDiv(totalAssets() + 1, totalSupply() + 10 ** _decimalsOffset(), rounding); + } + + /** + * @dev Deposit/mint common workflow. + */ + function _deposit(address caller, address receiver, uint256 assets, uint256 shares) internal virtual { + // If asset() is ERC-777, `transferFrom` can trigger a reentrancy BEFORE the transfer happens through the + // `tokensToSend` hook. On the other hand, the `tokenReceived` hook, that is triggered after the transfer, + // calls the vault, which is assumed not malicious. + // + // Conclusion: we need to do the transfer before we mint so that any reentrancy would happen before the + // assets are transferred and before the shares are minted, which is a valid state. + // slither-disable-next-line reentrancy-no-eth + SafeERC20.safeTransferFrom(IERC20(asset()), caller, address(this), assets); + _mint(receiver, shares); + + emit Deposit(caller, receiver, assets, shares); + } + + /** + * @dev Withdraw/redeem common workflow. + */ + function _withdraw( + address caller, + address receiver, + address owner, + uint256 assets, + uint256 shares + ) internal virtual { + if (caller != owner) { + _spendAllowance(owner, caller, shares); + } + + // If asset() is ERC-777, `transfer` can trigger a reentrancy AFTER the transfer happens through the + // `tokensReceived` hook. On the other hand, the `tokensToSend` hook, that is triggered before the transfer, + // calls the vault, which is assumed not malicious. + // + // Conclusion: we need to do the transfer after the burn so that any reentrancy would happen after the + // shares are burned and after the assets are transferred, which is a valid state. + _burn(owner, shares); + SafeERC20.safeTransfer(IERC20(asset()), receiver, assets); + + emit Withdraw(caller, receiver, owner, assets, shares); + } + + function _decimalsOffset() internal view virtual returns (uint8) { + return 0; + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/extensions/IERC20Metadata.sol b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/extensions/IERC20Metadata.sol new file mode 100644 index 00000000..87bbafa8 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/extensions/IERC20Metadata.sol @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/extensions/IERC20Metadata.sol) + +pragma solidity >=0.6.2; + +import {IERC20} from "../IERC20.sol"; + +/** + * @dev Interface for the optional metadata functions from the ERC-20 standard. + */ +interface IERC20Metadata is IERC20 { + /** + * @dev Returns the name of the token. + */ + function name() external view returns (string memory); + + /** + * @dev Returns the symbol of the token. + */ + function symbol() external view returns (string memory); + + /** + * @dev Returns the decimals places of the token. + */ + function decimals() external view returns (uint8); +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/extensions/IERC20Permit.sol b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/extensions/IERC20Permit.sol new file mode 100644 index 00000000..65488bab --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/extensions/IERC20Permit.sol @@ -0,0 +1,90 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/extensions/IERC20Permit.sol) + +pragma solidity >=0.4.16; + +/** + * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in + * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612]. + * + * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by + * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't + * need to send a transaction, and thus is not required to hold Ether at all. + * + * ==== Security Considerations + * + * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature + * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be + * considered as an intention to spend the allowance in any specific way. The second is that because permits have + * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should + * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be + * generally recommended is: + * + * ```solidity + * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public { + * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {} + * doThing(..., value); + * } + * + * function doThing(..., uint256 value) public { + * token.safeTransferFrom(msg.sender, address(this), value); + * ... + * } + * ``` + * + * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of + * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also + * {SafeERC20-safeTransferFrom}). + * + * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so + * contracts should have entry points that don't rely on permit. + */ +interface IERC20Permit { + /** + * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, + * given ``owner``'s signed approval. + * + * IMPORTANT: The same issues {IERC20-approve} has related to transaction + * ordering also apply here. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `deadline` must be a timestamp in the future. + * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` + * over the EIP712-formatted function arguments. + * - the signature must use ``owner``'s current nonce (see {nonces}). + * + * For more information on the signature format, see the + * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP + * section]. + * + * CAUTION: See Security Considerations above. + */ + function permit( + address owner, + address spender, + uint256 value, + uint256 deadline, + uint8 v, + bytes32 r, + bytes32 s + ) external; + + /** + * @dev Returns the current nonce for `owner`. This value must be + * included whenever a signature is generated for {permit}. + * + * Every successful call to {permit} increases ``owner``'s nonce by one. This + * prevents a signature from being used multiple times. + */ + function nonces(address owner) external view returns (uint256); + + /** + * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. + */ + // solhint-disable-next-line func-name-mixedcase + function DOMAIN_SEPARATOR() external view returns (bytes32); +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/extensions/draft-ERC20Bridgeable.sol b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/extensions/draft-ERC20Bridgeable.sol new file mode 100644 index 00000000..34730139 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/extensions/draft-ERC20Bridgeable.sol @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/extensions/draft-ERC20Bridgeable.sol) + +pragma solidity ^0.8.20; + +import {ERC20} from "../ERC20.sol"; +import {ERC165, IERC165} from "../../../utils/introspection/ERC165.sol"; +import {IERC7802} from "../../../interfaces/draft-IERC7802.sol"; + +/** + * @dev ERC20 extension that implements the standard token interface according to + * https://eips.ethereum.org/EIPS/eip-7802[ERC-7802]. + */ +abstract contract ERC20Bridgeable is ERC20, ERC165, IERC7802 { + /// @dev Modifier to restrict access to the token bridge. + modifier onlyTokenBridge() { + // Token bridge should never be impersonated using a relayer/forwarder. Using msg.sender is preferable to + // _msgSender() for security reasons. + _checkTokenBridge(msg.sender); + _; + } + + /// @inheritdoc ERC165 + function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { + return interfaceId == type(IERC7802).interfaceId || super.supportsInterface(interfaceId); + } + + /** + * @dev See {IERC7802-crosschainMint}. Emits a {IERC7802-CrosschainMint} event. + */ + function crosschainMint(address to, uint256 value) public virtual override onlyTokenBridge { + _mint(to, value); + emit CrosschainMint(to, value, _msgSender()); + } + + /** + * @dev See {IERC7802-crosschainBurn}. Emits a {IERC7802-CrosschainBurn} event. + */ + function crosschainBurn(address from, uint256 value) public virtual override onlyTokenBridge { + _burn(from, value); + emit CrosschainBurn(from, value, _msgSender()); + } + + /** + * @dev Checks if the caller is a trusted token bridge. MUST revert otherwise. + * + * Developers should implement this function using an access control mechanism that allows + * customizing the list of allowed senders. Consider using {AccessControl} or {AccessManaged}. + */ + function _checkTokenBridge(address caller) internal virtual; +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/extensions/draft-ERC20TemporaryApproval.sol b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/extensions/draft-ERC20TemporaryApproval.sol new file mode 100644 index 00000000..357daa93 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/extensions/draft-ERC20TemporaryApproval.sol @@ -0,0 +1,119 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC20/extensions/draft-ERC20TemporaryApproval.sol) + +pragma solidity ^0.8.24; + +import {IERC20, ERC20} from "../ERC20.sol"; +import {IERC7674} from "../../../interfaces/draft-IERC7674.sol"; +import {Math} from "../../../utils/math/Math.sol"; +import {SlotDerivation} from "../../../utils/SlotDerivation.sol"; +import {TransientSlot} from "../../../utils/TransientSlot.sol"; + +/** + * @dev Extension of {ERC20} that adds support for temporary allowances following ERC-7674. + * + * WARNING: This is a draft contract. The corresponding ERC is still subject to changes. + * + * _Available since v5.1._ + */ +abstract contract ERC20TemporaryApproval is ERC20, IERC7674 { + using SlotDerivation for bytes32; + using TransientSlot for bytes32; + using TransientSlot for TransientSlot.Uint256Slot; + + // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.ERC20_TEMPORARY_APPROVAL_STORAGE")) - 1)) & ~bytes32(uint256(0xff)) + bytes32 private constant ERC20_TEMPORARY_APPROVAL_STORAGE = + 0xea2d0e77a01400d0111492b1321103eed560d8fe44b9a7c2410407714583c400; + + /** + * @dev {allowance} override that includes the temporary allowance when looking up the current allowance. If + * adding up the persistent and the temporary allowances result in an overflow, type(uint256).max is returned. + */ + function allowance(address owner, address spender) public view virtual override(IERC20, ERC20) returns (uint256) { + (bool success, uint256 amount) = Math.tryAdd( + super.allowance(owner, spender), + _temporaryAllowance(owner, spender) + ); + return success ? amount : type(uint256).max; + } + + /** + * @dev Internal getter for the current temporary allowance that `spender` has over `owner` tokens. + */ + function _temporaryAllowance(address owner, address spender) internal view virtual returns (uint256) { + return _temporaryAllowanceSlot(owner, spender).tload(); + } + + /** + * @dev Alternative to {approve} that sets a `value` amount of tokens as the temporary allowance of `spender` over + * the caller's tokens. + * + * Returns a boolean value indicating whether the operation succeeded. + * + * Requirements: + * - `spender` cannot be the zero address. + * + * Does NOT emit an {Approval} event. + */ + function temporaryApprove(address spender, uint256 value) public virtual returns (bool) { + _temporaryApprove(_msgSender(), spender, value); + return true; + } + + /** + * @dev Sets `value` as the temporary allowance of `spender` over the `owner`'s tokens. + * + * This internal function is equivalent to `temporaryApprove`, and can be used to e.g. set automatic allowances + * for certain subsystems, etc. + * + * Requirements: + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + * + * Does NOT emit an {Approval} event. + */ + function _temporaryApprove(address owner, address spender, uint256 value) internal virtual { + if (owner == address(0)) { + revert ERC20InvalidApprover(address(0)); + } + if (spender == address(0)) { + revert ERC20InvalidSpender(address(0)); + } + _temporaryAllowanceSlot(owner, spender).tstore(value); + } + + /** + * @dev {_spendAllowance} override that consumes the temporary allowance (if any) before eventually falling back + * to consuming the persistent allowance. + * NOTE: This function skips calling `super._spendAllowance` if the temporary allowance + * is enough to cover the spending. + */ + function _spendAllowance(address owner, address spender, uint256 value) internal virtual override { + // load transient allowance + uint256 currentTemporaryAllowance = _temporaryAllowance(owner, spender); + + // Check and update (if needed) the temporary allowance + set remaining value + if (currentTemporaryAllowance > 0) { + // All value is covered by the infinite allowance. nothing left to spend, we can return early + if (currentTemporaryAllowance == type(uint256).max) { + return; + } + // check how much of the value is covered by the transient allowance + uint256 spendTemporaryAllowance = Math.min(currentTemporaryAllowance, value); + unchecked { + // decrease transient allowance accordingly + _temporaryApprove(owner, spender, currentTemporaryAllowance - spendTemporaryAllowance); + // update value necessary + value -= spendTemporaryAllowance; + } + } + // reduce any remaining value from the persistent allowance + if (value > 0) { + super._spendAllowance(owner, spender, value); + } + } + + function _temporaryAllowanceSlot(address owner, address spender) private pure returns (TransientSlot.Uint256Slot) { + return ERC20_TEMPORARY_APPROVAL_STORAGE.deriveMapping(owner).deriveMapping(spender).asUint256(); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/utils/ERC1363Utils.sol b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/utils/ERC1363Utils.sol new file mode 100644 index 00000000..25577bc6 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/utils/ERC1363Utils.sol @@ -0,0 +1,95 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/utils/ERC1363Utils.sol) + +pragma solidity ^0.8.20; + +import {IERC1363Receiver} from "../../../interfaces/IERC1363Receiver.sol"; +import {IERC1363Spender} from "../../../interfaces/IERC1363Spender.sol"; + +/** + * @dev Library that provides common ERC-1363 utility functions. + * + * See https://eips.ethereum.org/EIPS/eip-1363[ERC-1363]. + */ +library ERC1363Utils { + /** + * @dev Indicates a failure with the token `receiver`. Used in transfers. + * @param receiver Address to which tokens are being transferred. + */ + error ERC1363InvalidReceiver(address receiver); + + /** + * @dev Indicates a failure with the token `spender`. Used in approvals. + * @param spender Address that may be allowed to operate on tokens without being their owner. + */ + error ERC1363InvalidSpender(address spender); + + /** + * @dev Performs a call to {IERC1363Receiver-onTransferReceived} on a target address. + * + * Requirements: + * + * - The target has code (i.e. is a contract). + * - The target `to` must implement the {IERC1363Receiver} interface. + * - The target must return the {IERC1363Receiver-onTransferReceived} selector to accept the transfer. + */ + function checkOnERC1363TransferReceived( + address operator, + address from, + address to, + uint256 value, + bytes memory data + ) internal { + if (to.code.length == 0) { + revert ERC1363InvalidReceiver(to); + } + + try IERC1363Receiver(to).onTransferReceived(operator, from, value, data) returns (bytes4 retval) { + if (retval != IERC1363Receiver.onTransferReceived.selector) { + revert ERC1363InvalidReceiver(to); + } + } catch (bytes memory reason) { + if (reason.length == 0) { + revert ERC1363InvalidReceiver(to); + } else { + assembly ("memory-safe") { + revert(add(reason, 0x20), mload(reason)) + } + } + } + } + + /** + * @dev Performs a call to {IERC1363Spender-onApprovalReceived} on a target address. + * + * Requirements: + * + * - The target has code (i.e. is a contract). + * - The target `spender` must implement the {IERC1363Spender} interface. + * - The target must return the {IERC1363Spender-onApprovalReceived} selector to accept the approval. + */ + function checkOnERC1363ApprovalReceived( + address operator, + address spender, + uint256 value, + bytes memory data + ) internal { + if (spender.code.length == 0) { + revert ERC1363InvalidSpender(spender); + } + + try IERC1363Spender(spender).onApprovalReceived(operator, value, data) returns (bytes4 retval) { + if (retval != IERC1363Spender.onApprovalReceived.selector) { + revert ERC1363InvalidSpender(spender); + } + } catch (bytes memory reason) { + if (reason.length == 0) { + revert ERC1363InvalidSpender(spender); + } else { + assembly ("memory-safe") { + revert(add(reason, 0x20), mload(reason)) + } + } + } + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/utils/SafeERC20.sol b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/utils/SafeERC20.sol new file mode 100644 index 00000000..883e8d30 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC20/utils/SafeERC20.sol @@ -0,0 +1,212 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC20/utils/SafeERC20.sol) + +pragma solidity ^0.8.20; + +import {IERC20} from "../IERC20.sol"; +import {IERC1363} from "../../../interfaces/IERC1363.sol"; + +/** + * @title SafeERC20 + * @dev Wrappers around ERC-20 operations that throw on failure (when the token + * contract returns false). Tokens that return no value (and instead revert or + * throw on failure) are also supported, non-reverting calls are assumed to be + * successful. + * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, + * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. + */ +library SafeERC20 { + /** + * @dev An operation with an ERC-20 token failed. + */ + error SafeERC20FailedOperation(address token); + + /** + * @dev Indicates a failed `decreaseAllowance` request. + */ + error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease); + + /** + * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, + * non-reverting calls are assumed to be successful. + */ + function safeTransfer(IERC20 token, address to, uint256 value) internal { + _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value))); + } + + /** + * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the + * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. + */ + function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { + _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value))); + } + + /** + * @dev Variant of {safeTransfer} that returns a bool instead of reverting if the operation is not successful. + */ + function trySafeTransfer(IERC20 token, address to, uint256 value) internal returns (bool) { + return _callOptionalReturnBool(token, abi.encodeCall(token.transfer, (to, value))); + } + + /** + * @dev Variant of {safeTransferFrom} that returns a bool instead of reverting if the operation is not successful. + */ + function trySafeTransferFrom(IERC20 token, address from, address to, uint256 value) internal returns (bool) { + return _callOptionalReturnBool(token, abi.encodeCall(token.transferFrom, (from, to, value))); + } + + /** + * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, + * non-reverting calls are assumed to be successful. + * + * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client" + * smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using + * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract + * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior. + */ + function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { + uint256 oldAllowance = token.allowance(address(this), spender); + forceApprove(token, spender, oldAllowance + value); + } + + /** + * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no + * value, non-reverting calls are assumed to be successful. + * + * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client" + * smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using + * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract + * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior. + */ + function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal { + unchecked { + uint256 currentAllowance = token.allowance(address(this), spender); + if (currentAllowance < requestedDecrease) { + revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease); + } + forceApprove(token, spender, currentAllowance - requestedDecrease); + } + } + + /** + * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, + * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval + * to be set to zero before setting it to a non-zero value, such as USDT. + * + * NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function + * only sets the "standard" allowance. Any temporary allowance will remain active, in addition to the value being + * set here. + */ + function forceApprove(IERC20 token, address spender, uint256 value) internal { + bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value)); + + if (!_callOptionalReturnBool(token, approvalCall)) { + _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0))); + _callOptionalReturn(token, approvalCall); + } + } + + /** + * @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no + * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when + * targeting contracts. + * + * Reverts if the returned value is other than `true`. + */ + function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal { + if (to.code.length == 0) { + safeTransfer(token, to, value); + } else if (!token.transferAndCall(to, value, data)) { + revert SafeERC20FailedOperation(address(token)); + } + } + + /** + * @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target + * has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when + * targeting contracts. + * + * Reverts if the returned value is other than `true`. + */ + function transferFromAndCallRelaxed( + IERC1363 token, + address from, + address to, + uint256 value, + bytes memory data + ) internal { + if (to.code.length == 0) { + safeTransferFrom(token, from, to, value); + } else if (!token.transferFromAndCall(from, to, value, data)) { + revert SafeERC20FailedOperation(address(token)); + } + } + + /** + * @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no + * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when + * targeting contracts. + * + * NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}. + * Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall} + * once without retrying, and relies on the returned value to be true. + * + * Reverts if the returned value is other than `true`. + */ + function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal { + if (to.code.length == 0) { + forceApprove(token, to, value); + } else if (!token.approveAndCall(to, value, data)) { + revert SafeERC20FailedOperation(address(token)); + } + } + + /** + * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement + * on the return value: the return value is optional (but if data is returned, it must not be false). + * @param token The token targeted by the call. + * @param data The call data (encoded using abi.encode or one of its variants). + * + * This is a variant of {_callOptionalReturnBool} that reverts if call fails to meet the requirements. + */ + function _callOptionalReturn(IERC20 token, bytes memory data) private { + uint256 returnSize; + uint256 returnValue; + assembly ("memory-safe") { + let success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20) + // bubble errors + if iszero(success) { + let ptr := mload(0x40) + returndatacopy(ptr, 0, returndatasize()) + revert(ptr, returndatasize()) + } + returnSize := returndatasize() + returnValue := mload(0) + } + + if (returnSize == 0 ? address(token).code.length == 0 : returnValue != 1) { + revert SafeERC20FailedOperation(address(token)); + } + } + + /** + * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement + * on the return value: the return value is optional (but if data is returned, it must not be false). + * @param token The token targeted by the call. + * @param data The call data (encoded using abi.encode or one of its variants). + * + * This is a variant of {_callOptionalReturn} that silently catches all reverts and returns a bool instead. + */ + function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { + bool success; + uint256 returnSize; + uint256 returnValue; + assembly ("memory-safe") { + success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20) + returnSize := returndatasize() + returnValue := mload(0) + } + return success && (returnSize == 0 ? address(token).code.length > 0 : returnValue == 1); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/token/ERC6909/draft-ERC6909.sol b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC6909/draft-ERC6909.sol new file mode 100644 index 00000000..6f5cdd6a --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC6909/draft-ERC6909.sol @@ -0,0 +1,224 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC6909/draft-ERC6909.sol) + +pragma solidity ^0.8.20; + +import {IERC6909} from "../../interfaces/draft-IERC6909.sol"; +import {Context} from "../../utils/Context.sol"; +import {IERC165, ERC165} from "../../utils/introspection/ERC165.sol"; + +/** + * @dev Implementation of ERC-6909. + * See https://eips.ethereum.org/EIPS/eip-6909 + */ +contract ERC6909 is Context, ERC165, IERC6909 { + mapping(address owner => mapping(uint256 id => uint256)) private _balances; + + mapping(address owner => mapping(address operator => bool)) private _operatorApprovals; + + mapping(address owner => mapping(address spender => mapping(uint256 id => uint256))) private _allowances; + + error ERC6909InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 id); + error ERC6909InsufficientAllowance(address spender, uint256 allowance, uint256 needed, uint256 id); + error ERC6909InvalidApprover(address approver); + error ERC6909InvalidReceiver(address receiver); + error ERC6909InvalidSender(address sender); + error ERC6909InvalidSpender(address spender); + + /// @inheritdoc IERC165 + function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { + return interfaceId == type(IERC6909).interfaceId || super.supportsInterface(interfaceId); + } + + /// @inheritdoc IERC6909 + function balanceOf(address owner, uint256 id) public view virtual override returns (uint256) { + return _balances[owner][id]; + } + + /// @inheritdoc IERC6909 + function allowance(address owner, address spender, uint256 id) public view virtual override returns (uint256) { + return _allowances[owner][spender][id]; + } + + /// @inheritdoc IERC6909 + function isOperator(address owner, address spender) public view virtual override returns (bool) { + return _operatorApprovals[owner][spender]; + } + + /// @inheritdoc IERC6909 + function approve(address spender, uint256 id, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, id, amount); + return true; + } + + /// @inheritdoc IERC6909 + function setOperator(address spender, bool approved) public virtual override returns (bool) { + _setOperator(_msgSender(), spender, approved); + return true; + } + + /// @inheritdoc IERC6909 + function transfer(address receiver, uint256 id, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), receiver, id, amount); + return true; + } + + /// @inheritdoc IERC6909 + function transferFrom( + address sender, + address receiver, + uint256 id, + uint256 amount + ) public virtual override returns (bool) { + address caller = _msgSender(); + if (sender != caller && !isOperator(sender, caller)) { + _spendAllowance(sender, caller, id, amount); + } + _transfer(sender, receiver, id, amount); + return true; + } + + /** + * @dev Creates `amount` of token `id` and assigns them to `account`, by transferring it from address(0). + * Relies on the `_update` mechanism. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * NOTE: This function is not virtual, {_update} should be overridden instead. + */ + function _mint(address to, uint256 id, uint256 amount) internal { + if (to == address(0)) { + revert ERC6909InvalidReceiver(address(0)); + } + _update(address(0), to, id, amount); + } + + /** + * @dev Moves `amount` of token `id` from `from` to `to` without checking for approvals. This function verifies + * that neither the sender nor the receiver are address(0), which means it cannot mint or burn tokens. + * Relies on the `_update` mechanism. + * + * Emits a {Transfer} event. + * + * NOTE: This function is not virtual, {_update} should be overridden instead. + */ + function _transfer(address from, address to, uint256 id, uint256 amount) internal { + if (from == address(0)) { + revert ERC6909InvalidSender(address(0)); + } + if (to == address(0)) { + revert ERC6909InvalidReceiver(address(0)); + } + _update(from, to, id, amount); + } + + /** + * @dev Destroys a `amount` of token `id` from `account`. + * Relies on the `_update` mechanism. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * NOTE: This function is not virtual, {_update} should be overridden instead + */ + function _burn(address from, uint256 id, uint256 amount) internal { + if (from == address(0)) { + revert ERC6909InvalidSender(address(0)); + } + _update(from, address(0), id, amount); + } + + /** + * @dev Transfers `amount` of token `id` from `from` to `to`, or alternatively mints (or burns) if `from` + * (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding + * this function. + * + * Emits a {Transfer} event. + */ + function _update(address from, address to, uint256 id, uint256 amount) internal virtual { + address caller = _msgSender(); + + if (from != address(0)) { + uint256 fromBalance = _balances[from][id]; + if (fromBalance < amount) { + revert ERC6909InsufficientBalance(from, fromBalance, amount, id); + } + unchecked { + // Overflow not possible: amount <= fromBalance. + _balances[from][id] = fromBalance - amount; + } + } + if (to != address(0)) { + _balances[to][id] += amount; + } + + emit Transfer(caller, from, to, id, amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner`'s `id` tokens. + * + * This internal function is equivalent to `approve`, and can be used to e.g. set automatic allowances for certain + * subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve(address owner, address spender, uint256 id, uint256 amount) internal virtual { + if (owner == address(0)) { + revert ERC6909InvalidApprover(address(0)); + } + if (spender == address(0)) { + revert ERC6909InvalidSpender(address(0)); + } + _allowances[owner][spender][id] = amount; + emit Approval(owner, spender, id, amount); + } + + /** + * @dev Approve `spender` to operate on all of `owner`'s tokens + * + * This internal function is equivalent to `setOperator`, and can be used to e.g. set automatic allowances for + * certain subsystems, etc. + * + * Emits an {OperatorSet} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _setOperator(address owner, address spender, bool approved) internal virtual { + if (owner == address(0)) { + revert ERC6909InvalidApprover(address(0)); + } + if (spender == address(0)) { + revert ERC6909InvalidSpender(address(0)); + } + _operatorApprovals[owner][spender] = approved; + emit OperatorSet(owner, spender, approved); + } + + /** + * @dev Updates `owner`'s allowance for `spender` based on spent `amount`. + * + * Does not update the allowance value in case of infinite allowance. + * Revert if not enough allowance is available. + * + * Does not emit an {Approval} event. + */ + function _spendAllowance(address owner, address spender, uint256 id, uint256 amount) internal virtual { + uint256 currentAllowance = allowance(owner, spender, id); + if (currentAllowance < type(uint256).max) { + if (currentAllowance < amount) { + revert ERC6909InsufficientAllowance(spender, currentAllowance, amount, id); + } + unchecked { + _allowances[owner][spender][id] = currentAllowance - amount; + } + } + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/token/ERC6909/extensions/draft-ERC6909ContentURI.sol b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC6909/extensions/draft-ERC6909ContentURI.sol new file mode 100644 index 00000000..9d082c06 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC6909/extensions/draft-ERC6909ContentURI.sol @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC6909/extensions/draft-ERC6909ContentURI.sol) + +pragma solidity ^0.8.20; + +import {ERC6909} from "../draft-ERC6909.sol"; +import {IERC6909ContentURI} from "../../../interfaces/draft-IERC6909.sol"; + +/** + * @dev Implementation of the Content URI extension defined in ERC6909. + */ +contract ERC6909ContentURI is ERC6909, IERC6909ContentURI { + string private _contractURI; + mapping(uint256 id => string) private _tokenURIs; + + /// @dev Event emitted when the contract URI is changed. See https://eips.ethereum.org/EIPS/eip-7572[ERC-7572] for details. + event ContractURIUpdated(); + + /// @dev See {IERC1155-URI} + event URI(string value, uint256 indexed id); + + /// @inheritdoc IERC6909ContentURI + function contractURI() public view virtual override returns (string memory) { + return _contractURI; + } + + /// @inheritdoc IERC6909ContentURI + function tokenURI(uint256 id) public view virtual override returns (string memory) { + return _tokenURIs[id]; + } + + /** + * @dev Sets the {contractURI} for the contract. + * + * Emits a {ContractURIUpdated} event. + */ + function _setContractURI(string memory newContractURI) internal virtual { + _contractURI = newContractURI; + + emit ContractURIUpdated(); + } + + /** + * @dev Sets the {tokenURI} for a given token of type `id`. + * + * Emits a {URI} event. + */ + function _setTokenURI(uint256 id, string memory newTokenURI) internal virtual { + _tokenURIs[id] = newTokenURI; + + emit URI(newTokenURI, id); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/token/ERC6909/extensions/draft-ERC6909Metadata.sol b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC6909/extensions/draft-ERC6909Metadata.sol new file mode 100644 index 00000000..31efebe8 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC6909/extensions/draft-ERC6909Metadata.sol @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC6909/extensions/draft-ERC6909Metadata.sol) + +pragma solidity ^0.8.20; + +import {ERC6909} from "../draft-ERC6909.sol"; +import {IERC6909Metadata} from "../../../interfaces/draft-IERC6909.sol"; + +/** + * @dev Implementation of the Metadata extension defined in ERC6909. Exposes the name, symbol, and decimals of each token id. + */ +contract ERC6909Metadata is ERC6909, IERC6909Metadata { + struct TokenMetadata { + string name; + string symbol; + uint8 decimals; + } + + mapping(uint256 id => TokenMetadata) private _tokenMetadata; + + /// @dev The name of the token of type `id` was updated to `newName`. + event ERC6909NameUpdated(uint256 indexed id, string newName); + + /// @dev The symbol for the token of type `id` was updated to `newSymbol`. + event ERC6909SymbolUpdated(uint256 indexed id, string newSymbol); + + /// @dev The decimals value for token of type `id` was updated to `newDecimals`. + event ERC6909DecimalsUpdated(uint256 indexed id, uint8 newDecimals); + + /// @inheritdoc IERC6909Metadata + function name(uint256 id) public view virtual override returns (string memory) { + return _tokenMetadata[id].name; + } + + /// @inheritdoc IERC6909Metadata + function symbol(uint256 id) public view virtual override returns (string memory) { + return _tokenMetadata[id].symbol; + } + + /// @inheritdoc IERC6909Metadata + function decimals(uint256 id) public view virtual override returns (uint8) { + return _tokenMetadata[id].decimals; + } + + /** + * @dev Sets the `name` for a given token of type `id`. + * + * Emits an {ERC6909NameUpdated} event. + */ + function _setName(uint256 id, string memory newName) internal virtual { + _tokenMetadata[id].name = newName; + + emit ERC6909NameUpdated(id, newName); + } + + /** + * @dev Sets the `symbol` for a given token of type `id`. + * + * Emits an {ERC6909SymbolUpdated} event. + */ + function _setSymbol(uint256 id, string memory newSymbol) internal virtual { + _tokenMetadata[id].symbol = newSymbol; + + emit ERC6909SymbolUpdated(id, newSymbol); + } + + /** + * @dev Sets the `decimals` for a given token of type `id`. + * + * Emits an {ERC6909DecimalsUpdated} event. + */ + function _setDecimals(uint256 id, uint8 newDecimals) internal virtual { + _tokenMetadata[id].decimals = newDecimals; + + emit ERC6909DecimalsUpdated(id, newDecimals); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/token/ERC6909/extensions/draft-ERC6909TokenSupply.sol b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC6909/extensions/draft-ERC6909TokenSupply.sol new file mode 100644 index 00000000..0fd4c224 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC6909/extensions/draft-ERC6909TokenSupply.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC6909/extensions/draft-ERC6909TokenSupply.sol) + +pragma solidity ^0.8.20; + +import {ERC6909} from "../draft-ERC6909.sol"; +import {IERC6909TokenSupply} from "../../../interfaces/draft-IERC6909.sol"; + +/** + * @dev Implementation of the Token Supply extension defined in ERC6909. + * Tracks the total supply of each token id individually. + */ +contract ERC6909TokenSupply is ERC6909, IERC6909TokenSupply { + mapping(uint256 id => uint256) private _totalSupplies; + + /// @inheritdoc IERC6909TokenSupply + function totalSupply(uint256 id) public view virtual override returns (uint256) { + return _totalSupplies[id]; + } + + /// @dev Override the `_update` function to update the total supply of each token id as necessary. + function _update(address from, address to, uint256 id, uint256 amount) internal virtual override { + super._update(from, to, id, amount); + + if (from == address(0)) { + _totalSupplies[id] += amount; + } + if (to == address(0)) { + unchecked { + // amount <= _balances[from][id] <= _totalSupplies[id] + _totalSupplies[id] -= amount; + } + } + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/token/ERC721/ERC721.sol b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC721/ERC721.sol new file mode 100644 index 00000000..2867cd12 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC721/ERC721.sol @@ -0,0 +1,430 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC721/ERC721.sol) + +pragma solidity ^0.8.20; + +import {IERC721} from "./IERC721.sol"; +import {IERC721Metadata} from "./extensions/IERC721Metadata.sol"; +import {ERC721Utils} from "./utils/ERC721Utils.sol"; +import {Context} from "../../utils/Context.sol"; +import {Strings} from "../../utils/Strings.sol"; +import {IERC165, ERC165} from "../../utils/introspection/ERC165.sol"; +import {IERC721Errors} from "../../interfaces/draft-IERC6093.sol"; + +/** + * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC-721] Non-Fungible Token Standard, including + * the Metadata extension, but not including the Enumerable extension, which is available separately as + * {ERC721Enumerable}. + */ +abstract contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Errors { + using Strings for uint256; + + // Token name + string private _name; + + // Token symbol + string private _symbol; + + mapping(uint256 tokenId => address) private _owners; + + mapping(address owner => uint256) private _balances; + + mapping(uint256 tokenId => address) private _tokenApprovals; + + mapping(address owner => mapping(address operator => bool)) private _operatorApprovals; + + /** + * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /// @inheritdoc IERC165 + function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { + return + interfaceId == type(IERC721).interfaceId || + interfaceId == type(IERC721Metadata).interfaceId || + super.supportsInterface(interfaceId); + } + + /// @inheritdoc IERC721 + function balanceOf(address owner) public view virtual returns (uint256) { + if (owner == address(0)) { + revert ERC721InvalidOwner(address(0)); + } + return _balances[owner]; + } + + /// @inheritdoc IERC721 + function ownerOf(uint256 tokenId) public view virtual returns (address) { + return _requireOwned(tokenId); + } + + /// @inheritdoc IERC721Metadata + function name() public view virtual returns (string memory) { + return _name; + } + + /// @inheritdoc IERC721Metadata + function symbol() public view virtual returns (string memory) { + return _symbol; + } + + /// @inheritdoc IERC721Metadata + function tokenURI(uint256 tokenId) public view virtual returns (string memory) { + _requireOwned(tokenId); + + string memory baseURI = _baseURI(); + return bytes(baseURI).length > 0 ? string.concat(baseURI, tokenId.toString()) : ""; + } + + /** + * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each + * token will be the concatenation of the `baseURI` and the `tokenId`. Empty + * by default, can be overridden in child contracts. + */ + function _baseURI() internal view virtual returns (string memory) { + return ""; + } + + /// @inheritdoc IERC721 + function approve(address to, uint256 tokenId) public virtual { + _approve(to, tokenId, _msgSender()); + } + + /// @inheritdoc IERC721 + function getApproved(uint256 tokenId) public view virtual returns (address) { + _requireOwned(tokenId); + + return _getApproved(tokenId); + } + + /// @inheritdoc IERC721 + function setApprovalForAll(address operator, bool approved) public virtual { + _setApprovalForAll(_msgSender(), operator, approved); + } + + /// @inheritdoc IERC721 + function isApprovedForAll(address owner, address operator) public view virtual returns (bool) { + return _operatorApprovals[owner][operator]; + } + + /// @inheritdoc IERC721 + function transferFrom(address from, address to, uint256 tokenId) public virtual { + if (to == address(0)) { + revert ERC721InvalidReceiver(address(0)); + } + // Setting an "auth" arguments enables the `_isAuthorized` check which verifies that the token exists + // (from != 0). Therefore, it is not needed to verify that the return value is not 0 here. + address previousOwner = _update(to, tokenId, _msgSender()); + if (previousOwner != from) { + revert ERC721IncorrectOwner(from, tokenId, previousOwner); + } + } + + /// @inheritdoc IERC721 + function safeTransferFrom(address from, address to, uint256 tokenId) public { + safeTransferFrom(from, to, tokenId, ""); + } + + /// @inheritdoc IERC721 + function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public virtual { + transferFrom(from, to, tokenId); + ERC721Utils.checkOnERC721Received(_msgSender(), from, to, tokenId, data); + } + + /** + * @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist + * + * IMPORTANT: Any overrides to this function that add ownership of tokens not tracked by the + * core ERC-721 logic MUST be matched with the use of {_increaseBalance} to keep balances + * consistent with ownership. The invariant to preserve is that for any address `a` the value returned by + * `balanceOf(a)` must be equal to the number of tokens such that `_ownerOf(tokenId)` is `a`. + */ + function _ownerOf(uint256 tokenId) internal view virtual returns (address) { + return _owners[tokenId]; + } + + /** + * @dev Returns the approved address for `tokenId`. Returns 0 if `tokenId` is not minted. + */ + function _getApproved(uint256 tokenId) internal view virtual returns (address) { + return _tokenApprovals[tokenId]; + } + + /** + * @dev Returns whether `spender` is allowed to manage `owner`'s tokens, or `tokenId` in + * particular (ignoring whether it is owned by `owner`). + * + * WARNING: This function assumes that `owner` is the actual owner of `tokenId` and does not verify this + * assumption. + */ + function _isAuthorized(address owner, address spender, uint256 tokenId) internal view virtual returns (bool) { + return + spender != address(0) && + (owner == spender || isApprovedForAll(owner, spender) || _getApproved(tokenId) == spender); + } + + /** + * @dev Checks if `spender` can operate on `tokenId`, assuming the provided `owner` is the actual owner. + * Reverts if: + * - `spender` does not have approval from `owner` for `tokenId`. + * - `spender` does not have approval to manage all of `owner`'s assets. + * + * WARNING: This function assumes that `owner` is the actual owner of `tokenId` and does not verify this + * assumption. + */ + function _checkAuthorized(address owner, address spender, uint256 tokenId) internal view virtual { + if (!_isAuthorized(owner, spender, tokenId)) { + if (owner == address(0)) { + revert ERC721NonexistentToken(tokenId); + } else { + revert ERC721InsufficientApproval(spender, tokenId); + } + } + } + + /** + * @dev Unsafe write access to the balances, used by extensions that "mint" tokens using an {ownerOf} override. + * + * NOTE: the value is limited to type(uint128).max. This protect against _balance overflow. It is unrealistic that + * a uint256 would ever overflow from increments when these increments are bounded to uint128 values. + * + * WARNING: Increasing an account's balance using this function tends to be paired with an override of the + * {_ownerOf} function to resolve the ownership of the corresponding tokens so that balances and ownership + * remain consistent with one another. + */ + function _increaseBalance(address account, uint128 value) internal virtual { + unchecked { + _balances[account] += value; + } + } + + /** + * @dev Transfers `tokenId` from its current owner to `to`, or alternatively mints (or burns) if the current owner + * (or `to`) is the zero address. Returns the owner of the `tokenId` before the update. + * + * The `auth` argument is optional. If the value passed is non 0, then this function will check that + * `auth` is either the owner of the token, or approved to operate on the token (by the owner). + * + * Emits a {Transfer} event. + * + * NOTE: If overriding this function in a way that tracks balances, see also {_increaseBalance}. + */ + function _update(address to, uint256 tokenId, address auth) internal virtual returns (address) { + address from = _ownerOf(tokenId); + + // Perform (optional) operator check + if (auth != address(0)) { + _checkAuthorized(from, auth, tokenId); + } + + // Execute the update + if (from != address(0)) { + // Clear approval. No need to re-authorize or emit the Approval event + _approve(address(0), tokenId, address(0), false); + + unchecked { + _balances[from] -= 1; + } + } + + if (to != address(0)) { + unchecked { + _balances[to] += 1; + } + } + + _owners[tokenId] = to; + + emit Transfer(from, to, tokenId); + + return from; + } + + /** + * @dev Mints `tokenId` and transfers it to `to`. + * + * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible + * + * Requirements: + * + * - `tokenId` must not exist. + * - `to` cannot be the zero address. + * + * Emits a {Transfer} event. + */ + function _mint(address to, uint256 tokenId) internal { + if (to == address(0)) { + revert ERC721InvalidReceiver(address(0)); + } + address previousOwner = _update(to, tokenId, address(0)); + if (previousOwner != address(0)) { + revert ERC721InvalidSender(address(0)); + } + } + + /** + * @dev Mints `tokenId`, transfers it to `to` and checks for `to` acceptance. + * + * Requirements: + * + * - `tokenId` must not exist. + * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. + * + * Emits a {Transfer} event. + */ + function _safeMint(address to, uint256 tokenId) internal { + _safeMint(to, tokenId, ""); + } + + /** + * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is + * forwarded in {IERC721Receiver-onERC721Received} to contract recipients. + */ + function _safeMint(address to, uint256 tokenId, bytes memory data) internal virtual { + _mint(to, tokenId); + ERC721Utils.checkOnERC721Received(_msgSender(), address(0), to, tokenId, data); + } + + /** + * @dev Destroys `tokenId`. + * The approval is cleared when the token is burned. + * This is an internal function that does not check if the sender is authorized to operate on the token. + * + * Requirements: + * + * - `tokenId` must exist. + * + * Emits a {Transfer} event. + */ + function _burn(uint256 tokenId) internal { + address previousOwner = _update(address(0), tokenId, address(0)); + if (previousOwner == address(0)) { + revert ERC721NonexistentToken(tokenId); + } + } + + /** + * @dev Transfers `tokenId` from `from` to `to`. + * As opposed to {transferFrom}, this imposes no restrictions on msg.sender. + * + * Requirements: + * + * - `to` cannot be the zero address. + * - `tokenId` token must be owned by `from`. + * + * Emits a {Transfer} event. + */ + function _transfer(address from, address to, uint256 tokenId) internal { + if (to == address(0)) { + revert ERC721InvalidReceiver(address(0)); + } + address previousOwner = _update(to, tokenId, address(0)); + if (previousOwner == address(0)) { + revert ERC721NonexistentToken(tokenId); + } else if (previousOwner != from) { + revert ERC721IncorrectOwner(from, tokenId, previousOwner); + } + } + + /** + * @dev Safely transfers `tokenId` token from `from` to `to`, checking that contract recipients + * are aware of the ERC-721 standard to prevent tokens from being forever locked. + * + * `data` is additional data, it has no specified format and it is sent in call to `to`. + * + * This internal function is like {safeTransferFrom} in the sense that it invokes + * {IERC721Receiver-onERC721Received} on the receiver, and can be used to e.g. + * implement alternative mechanisms to perform token transfer, such as signature-based. + * + * Requirements: + * + * - `tokenId` token must exist and be owned by `from`. + * - `to` cannot be the zero address. + * - `from` cannot be the zero address. + * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. + * + * Emits a {Transfer} event. + */ + function _safeTransfer(address from, address to, uint256 tokenId) internal { + _safeTransfer(from, to, tokenId, ""); + } + + /** + * @dev Same as {xref-ERC721-_safeTransfer-address-address-uint256-}[`_safeTransfer`], with an additional `data` parameter which is + * forwarded in {IERC721Receiver-onERC721Received} to contract recipients. + */ + function _safeTransfer(address from, address to, uint256 tokenId, bytes memory data) internal virtual { + _transfer(from, to, tokenId); + ERC721Utils.checkOnERC721Received(_msgSender(), from, to, tokenId, data); + } + + /** + * @dev Approve `to` to operate on `tokenId` + * + * The `auth` argument is optional. If the value passed is non 0, then this function will check that `auth` is + * either the owner of the token, or approved to operate on all tokens held by this owner. + * + * Emits an {Approval} event. + * + * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument. + */ + function _approve(address to, uint256 tokenId, address auth) internal { + _approve(to, tokenId, auth, true); + } + + /** + * @dev Variant of `_approve` with an optional flag to enable or disable the {Approval} event. The event is not + * emitted in the context of transfers. + */ + function _approve(address to, uint256 tokenId, address auth, bool emitEvent) internal virtual { + // Avoid reading the owner unless necessary + if (emitEvent || auth != address(0)) { + address owner = _requireOwned(tokenId); + + // We do not use _isAuthorized because single-token approvals should not be able to call approve + if (auth != address(0) && owner != auth && !isApprovedForAll(owner, auth)) { + revert ERC721InvalidApprover(auth); + } + + if (emitEvent) { + emit Approval(owner, to, tokenId); + } + } + + _tokenApprovals[tokenId] = to; + } + + /** + * @dev Approve `operator` to operate on all of `owner` tokens + * + * Requirements: + * - operator can't be the address zero. + * + * Emits an {ApprovalForAll} event. + */ + function _setApprovalForAll(address owner, address operator, bool approved) internal virtual { + if (operator == address(0)) { + revert ERC721InvalidOperator(operator); + } + _operatorApprovals[owner][operator] = approved; + emit ApprovalForAll(owner, operator, approved); + } + + /** + * @dev Reverts if the `tokenId` doesn't have a current owner (it hasn't been minted, or it has been burned). + * Returns the owner. + * + * Overrides to ownership logic should be done to {_ownerOf}. + */ + function _requireOwned(uint256 tokenId) internal view returns (address) { + address owner = _ownerOf(tokenId); + if (owner == address(0)) { + revert ERC721NonexistentToken(tokenId); + } + return owner; + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/token/ERC721/IERC721.sol b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC721/IERC721.sol new file mode 100644 index 00000000..74982034 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC721/IERC721.sol @@ -0,0 +1,135 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC721/IERC721.sol) + +pragma solidity >=0.6.2; + +import {IERC165} from "../../utils/introspection/IERC165.sol"; + +/** + * @dev Required interface of an ERC-721 compliant contract. + */ +interface IERC721 is IERC165 { + /** + * @dev Emitted when `tokenId` token is transferred from `from` to `to`. + */ + event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); + + /** + * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. + */ + event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); + + /** + * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. + */ + event ApprovalForAll(address indexed owner, address indexed operator, bool approved); + + /** + * @dev Returns the number of tokens in ``owner``'s account. + */ + function balanceOf(address owner) external view returns (uint256 balance); + + /** + * @dev Returns the owner of the `tokenId` token. + * + * Requirements: + * + * - `tokenId` must exist. + */ + function ownerOf(uint256 tokenId) external view returns (address owner); + + /** + * @dev Safely transfers `tokenId` token from `from` to `to`. + * + * Requirements: + * + * - `from` cannot be the zero address. + * - `to` cannot be the zero address. + * - `tokenId` token must exist and be owned by `from`. + * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. + * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon + * a safe transfer. + * + * Emits a {Transfer} event. + */ + function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external; + + /** + * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients + * are aware of the ERC-721 protocol to prevent tokens from being forever locked. + * + * Requirements: + * + * - `from` cannot be the zero address. + * - `to` cannot be the zero address. + * - `tokenId` token must exist and be owned by `from`. + * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or + * {setApprovalForAll}. + * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon + * a safe transfer. + * + * Emits a {Transfer} event. + */ + function safeTransferFrom(address from, address to, uint256 tokenId) external; + + /** + * @dev Transfers `tokenId` token from `from` to `to`. + * + * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC-721 + * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must + * understand this adds an external call which potentially creates a reentrancy vulnerability. + * + * Requirements: + * + * - `from` cannot be the zero address. + * - `to` cannot be the zero address. + * - `tokenId` token must be owned by `from`. + * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. + * + * Emits a {Transfer} event. + */ + function transferFrom(address from, address to, uint256 tokenId) external; + + /** + * @dev Gives permission to `to` to transfer `tokenId` token to another account. + * The approval is cleared when the token is transferred. + * + * Only a single account can be approved at a time, so approving the zero address clears previous approvals. + * + * Requirements: + * + * - The caller must own the token or be an approved operator. + * - `tokenId` must exist. + * + * Emits an {Approval} event. + */ + function approve(address to, uint256 tokenId) external; + + /** + * @dev Approve or remove `operator` as an operator for the caller. + * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. + * + * Requirements: + * + * - The `operator` cannot be the address zero. + * + * Emits an {ApprovalForAll} event. + */ + function setApprovalForAll(address operator, bool approved) external; + + /** + * @dev Returns the account approved for `tokenId` token. + * + * Requirements: + * + * - `tokenId` must exist. + */ + function getApproved(uint256 tokenId) external view returns (address operator); + + /** + * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. + * + * See {setApprovalForAll} + */ + function isApprovedForAll(address owner, address operator) external view returns (bool); +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/token/ERC721/IERC721Receiver.sol b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC721/IERC721Receiver.sol new file mode 100644 index 00000000..6110f0c2 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC721/IERC721Receiver.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC721/IERC721Receiver.sol) + +pragma solidity >=0.5.0; + +/** + * @title ERC-721 token receiver interface + * @dev Interface for any contract that wants to support safeTransfers + * from ERC-721 asset contracts. + */ +interface IERC721Receiver { + /** + * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom} + * by `operator` from `from`, this function is called. + * + * It must return its Solidity selector to confirm the token transfer. + * If any other value is returned or the interface is not implemented by the recipient, the transfer will be + * reverted. + * + * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`. + */ + function onERC721Received( + address operator, + address from, + uint256 tokenId, + bytes calldata data + ) external returns (bytes4); +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/token/ERC721/extensions/ERC721Burnable.sol b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC721/extensions/ERC721Burnable.sol new file mode 100644 index 00000000..c6d22455 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC721/extensions/ERC721Burnable.sol @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/extensions/ERC721Burnable.sol) + +pragma solidity ^0.8.20; + +import {ERC721} from "../ERC721.sol"; +import {Context} from "../../../utils/Context.sol"; + +/** + * @title ERC-721 Burnable Token + * @dev ERC-721 Token that can be burned (destroyed). + */ +abstract contract ERC721Burnable is Context, ERC721 { + /** + * @dev Burns `tokenId`. See {ERC721-_burn}. + * + * Requirements: + * + * - The caller must own `tokenId` or be an approved operator. + */ + function burn(uint256 tokenId) public virtual { + // Setting an "auth" arguments enables the `_isAuthorized` check which verifies that the token exists + // (from != 0). Therefore, it is not needed to verify that the return value is not 0 here. + _update(address(0), tokenId, _msgSender()); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/token/ERC721/extensions/ERC721Consecutive.sol b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC721/extensions/ERC721Consecutive.sol new file mode 100644 index 00000000..0f326736 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC721/extensions/ERC721Consecutive.sol @@ -0,0 +1,176 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC721/extensions/ERC721Consecutive.sol) + +pragma solidity ^0.8.20; + +import {ERC721} from "../ERC721.sol"; +import {IERC2309} from "../../../interfaces/IERC2309.sol"; +import {BitMaps} from "../../../utils/structs/BitMaps.sol"; +import {Checkpoints} from "../../../utils/structs/Checkpoints.sol"; + +/** + * @dev Implementation of the ERC-2309 "Consecutive Transfer Extension" as defined in + * https://eips.ethereum.org/EIPS/eip-2309[ERC-2309]. + * + * This extension allows the minting of large batches of tokens, during contract construction only. For upgradeable + * contracts this implies that batch minting is only available during proxy deployment, and not in subsequent upgrades. + * These batches are limited to 5000 tokens at a time by default to accommodate off-chain indexers. + * + * Using this extension removes the ability to mint single tokens during contract construction. This ability is + * regained after construction. During construction, only batch minting is allowed. + * + * IMPORTANT: This extension does not call the {_update} function for tokens minted in batch. Any logic added to this + * function through overrides will not be triggered when token are minted in batch. You may want to also override + * {_increaseBalance} or {_mintConsecutive} to account for these mints. + * + * IMPORTANT: When overriding {_mintConsecutive}, be careful about call ordering. {ownerOf} may return invalid + * values during the {_mintConsecutive} execution if the super call is not called first. To be safe, execute the + * super call before your custom logic. + */ +abstract contract ERC721Consecutive is IERC2309, ERC721 { + using BitMaps for BitMaps.BitMap; + using Checkpoints for Checkpoints.Trace160; + + Checkpoints.Trace160 private _sequentialOwnership; + BitMaps.BitMap private _sequentialBurn; + + /** + * @dev Batch mint is restricted to the constructor. + * Any batch mint not emitting the {IERC721-Transfer} event outside of the constructor + * is non ERC-721 compliant. + */ + error ERC721ForbiddenBatchMint(); + + /** + * @dev Exceeds the max amount of mints per batch. + */ + error ERC721ExceededMaxBatchMint(uint256 batchSize, uint256 maxBatch); + + /** + * @dev Individual minting is not allowed. + */ + error ERC721ForbiddenMint(); + + /** + * @dev Batch burn is not supported. + */ + error ERC721ForbiddenBatchBurn(); + + /** + * @dev Maximum size of a batch of consecutive tokens. This is designed to limit stress on off-chain indexing + * services that have to record one entry per token, and have protections against "unreasonably large" batches of + * tokens. + * + * NOTE: Overriding the default value of 5000 will not cause on-chain issues, but may result in the asset not being + * correctly supported by off-chain indexing services (including marketplaces). + */ + function _maxBatchSize() internal view virtual returns (uint96) { + return 5000; + } + + /** + * @dev See {ERC721-_ownerOf}. Override that checks the sequential ownership structure for tokens that have + * been minted as part of a batch, and not yet transferred. + */ + function _ownerOf(uint256 tokenId) internal view virtual override returns (address) { + address owner = super._ownerOf(tokenId); + + // If token is owned by the core, or beyond consecutive range, return base value + if (owner != address(0) || tokenId > type(uint96).max || tokenId < _firstConsecutiveId()) { + return owner; + } + + // Otherwise, check the token was not burned, and fetch ownership from the anchors + // Note: no need for safe cast, we know that tokenId <= type(uint96).max + return _sequentialBurn.get(tokenId) ? address(0) : address(_sequentialOwnership.lowerLookup(uint96(tokenId))); + } + + /** + * @dev Mint a batch of tokens of length `batchSize` for `to`. Returns the token id of the first token minted in the + * batch; if `batchSize` is 0, returns the number of consecutive ids minted so far. + * + * Requirements: + * + * - `batchSize` must not be greater than {_maxBatchSize}. + * - The function is called in the constructor of the contract (directly or indirectly). + * + * CAUTION: Does not emit a `Transfer` event. This is ERC-721 compliant as long as it is done inside of the + * constructor, which is enforced by this function. + * + * CAUTION: Does not invoke `onERC721Received` on the receiver. + * + * Emits a {IERC2309-ConsecutiveTransfer} event. + */ + function _mintConsecutive(address to, uint96 batchSize) internal virtual returns (uint96) { + uint96 next = _nextConsecutiveId(); + + // minting a batch of size 0 is a no-op + if (batchSize > 0) { + if (address(this).code.length > 0) { + revert ERC721ForbiddenBatchMint(); + } + if (to == address(0)) { + revert ERC721InvalidReceiver(address(0)); + } + + uint256 maxBatchSize = _maxBatchSize(); + if (batchSize > maxBatchSize) { + revert ERC721ExceededMaxBatchMint(batchSize, maxBatchSize); + } + + // push an ownership checkpoint & emit event + uint96 last = next + batchSize - 1; + _sequentialOwnership.push(last, uint160(to)); + + // The invariant required by this function is preserved because the new sequentialOwnership checkpoint + // is attributing ownership of `batchSize` new tokens to account `to`. + _increaseBalance(to, batchSize); + + emit ConsecutiveTransfer(next, last, address(0), to); + } + + return next; + } + + /** + * @dev See {ERC721-_update}. Override version that restricts normal minting to after construction. + * + * WARNING: Using {ERC721Consecutive} prevents minting during construction in favor of {_mintConsecutive}. + * After construction, {_mintConsecutive} is no longer available and minting through {_update} becomes available. + */ + function _update(address to, uint256 tokenId, address auth) internal virtual override returns (address) { + address previousOwner = super._update(to, tokenId, auth); + + // only mint after construction + if (previousOwner == address(0) && address(this).code.length == 0) { + revert ERC721ForbiddenMint(); + } + + // record burn + if ( + to == address(0) && // if we burn + tokenId < _nextConsecutiveId() && // and the tokenId was minted in a batch + !_sequentialBurn.get(tokenId) // and the token was never marked as burnt + ) { + _sequentialBurn.set(tokenId); + } + + return previousOwner; + } + + /** + * @dev Used to offset the first token id in `_nextConsecutiveId` + */ + function _firstConsecutiveId() internal view virtual returns (uint96) { + return 0; + } + + /** + * @dev Returns the next tokenId to mint using {_mintConsecutive}. It will return {_firstConsecutiveId} + * if no consecutive tokenId has been minted before. + */ + function _nextConsecutiveId() private view returns (uint96) { + (bool exists, uint96 latestId, ) = _sequentialOwnership.latestCheckpoint(); + return exists ? latestId + 1 : _firstConsecutiveId(); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/token/ERC721/extensions/ERC721Enumerable.sol b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC721/extensions/ERC721Enumerable.sol new file mode 100644 index 00000000..1231ffc9 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC721/extensions/ERC721Enumerable.sol @@ -0,0 +1,164 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC721/extensions/ERC721Enumerable.sol) + +pragma solidity ^0.8.20; + +import {ERC721} from "../ERC721.sol"; +import {IERC721Enumerable} from "./IERC721Enumerable.sol"; +import {IERC165} from "../../../utils/introspection/ERC165.sol"; + +/** + * @dev This implements an optional extension of {ERC721} defined in the ERC that adds enumerability + * of all the token ids in the contract as well as all token ids owned by each account. + * + * CAUTION: {ERC721} extensions that implement custom `balanceOf` logic, such as {ERC721Consecutive}, + * interfere with enumerability and should not be used together with {ERC721Enumerable}. + */ +abstract contract ERC721Enumerable is ERC721, IERC721Enumerable { + mapping(address owner => mapping(uint256 index => uint256)) private _ownedTokens; + mapping(uint256 tokenId => uint256) private _ownedTokensIndex; + + uint256[] private _allTokens; + mapping(uint256 tokenId => uint256) private _allTokensIndex; + + /** + * @dev An `owner`'s token query was out of bounds for `index`. + * + * NOTE: The owner being `address(0)` indicates a global out of bounds index. + */ + error ERC721OutOfBoundsIndex(address owner, uint256 index); + + /** + * @dev Batch mint is not allowed. + */ + error ERC721EnumerableForbiddenBatchMint(); + + /// @inheritdoc IERC165 + function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC721) returns (bool) { + return interfaceId == type(IERC721Enumerable).interfaceId || super.supportsInterface(interfaceId); + } + + /// @inheritdoc IERC721Enumerable + function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual returns (uint256) { + if (index >= balanceOf(owner)) { + revert ERC721OutOfBoundsIndex(owner, index); + } + return _ownedTokens[owner][index]; + } + + /// @inheritdoc IERC721Enumerable + function totalSupply() public view virtual returns (uint256) { + return _allTokens.length; + } + + /// @inheritdoc IERC721Enumerable + function tokenByIndex(uint256 index) public view virtual returns (uint256) { + if (index >= totalSupply()) { + revert ERC721OutOfBoundsIndex(address(0), index); + } + return _allTokens[index]; + } + + /// @inheritdoc ERC721 + function _update(address to, uint256 tokenId, address auth) internal virtual override returns (address) { + address previousOwner = super._update(to, tokenId, auth); + + if (previousOwner == address(0)) { + _addTokenToAllTokensEnumeration(tokenId); + } else if (previousOwner != to) { + _removeTokenFromOwnerEnumeration(previousOwner, tokenId); + } + if (to == address(0)) { + _removeTokenFromAllTokensEnumeration(tokenId); + } else if (previousOwner != to) { + _addTokenToOwnerEnumeration(to, tokenId); + } + + return previousOwner; + } + + /** + * @dev Private function to add a token to this extension's ownership-tracking data structures. + * @param to address representing the new owner of the given token ID + * @param tokenId uint256 ID of the token to be added to the tokens list of the given address + */ + function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private { + uint256 length = balanceOf(to) - 1; + _ownedTokens[to][length] = tokenId; + _ownedTokensIndex[tokenId] = length; + } + + /** + * @dev Private function to add a token to this extension's token tracking data structures. + * @param tokenId uint256 ID of the token to be added to the tokens list + */ + function _addTokenToAllTokensEnumeration(uint256 tokenId) private { + _allTokensIndex[tokenId] = _allTokens.length; + _allTokens.push(tokenId); + } + + /** + * @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that + * while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for + * gas optimizations e.g. when performing a transfer operation (avoiding double writes). + * This has O(1) time complexity, but alters the order of the _ownedTokens array. + * @param from address representing the previous owner of the given token ID + * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address + */ + function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private { + // To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and + // then delete the last slot (swap and pop). + + uint256 lastTokenIndex = balanceOf(from); + uint256 tokenIndex = _ownedTokensIndex[tokenId]; + + mapping(uint256 index => uint256) storage _ownedTokensByOwner = _ownedTokens[from]; + + // When the token to delete is the last token, the swap operation is unnecessary + if (tokenIndex != lastTokenIndex) { + uint256 lastTokenId = _ownedTokensByOwner[lastTokenIndex]; + + _ownedTokensByOwner[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token + _ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index + } + + // This also deletes the contents at the last position of the array + delete _ownedTokensIndex[tokenId]; + delete _ownedTokensByOwner[lastTokenIndex]; + } + + /** + * @dev Private function to remove a token from this extension's token tracking data structures. + * This has O(1) time complexity, but alters the order of the _allTokens array. + * @param tokenId uint256 ID of the token to be removed from the tokens list + */ + function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private { + // To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and + // then delete the last slot (swap and pop). + + uint256 lastTokenIndex = _allTokens.length - 1; + uint256 tokenIndex = _allTokensIndex[tokenId]; + + // When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so + // rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding + // an 'if' statement (like in _removeTokenFromOwnerEnumeration) + uint256 lastTokenId = _allTokens[lastTokenIndex]; + + _allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token + _allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index + + // This also deletes the contents at the last position of the array + delete _allTokensIndex[tokenId]; + _allTokens.pop(); + } + + /** + * See {ERC721-_increaseBalance}. We need that to account tokens that were minted in batch + */ + function _increaseBalance(address account, uint128 amount) internal virtual override { + if (amount > 0) { + revert ERC721EnumerableForbiddenBatchMint(); + } + super._increaseBalance(account, amount); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/token/ERC721/extensions/ERC721Pausable.sol b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC721/extensions/ERC721Pausable.sol new file mode 100644 index 00000000..9a75623c --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC721/extensions/ERC721Pausable.sol @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/extensions/ERC721Pausable.sol) + +pragma solidity ^0.8.20; + +import {ERC721} from "../ERC721.sol"; +import {Pausable} from "../../../utils/Pausable.sol"; + +/** + * @dev ERC-721 token with pausable token transfers, minting and burning. + * + * Useful for scenarios such as preventing trades until the end of an evaluation + * period, or having an emergency switch for freezing all token transfers in the + * event of a large bug. + * + * IMPORTANT: This contract does not include public pause and unpause functions. In + * addition to inheriting this contract, you must define both functions, invoking the + * {Pausable-_pause} and {Pausable-_unpause} internal functions, with appropriate + * access control, e.g. using {AccessControl} or {Ownable}. Not doing so will + * make the contract pause mechanism of the contract unreachable, and thus unusable. + */ +abstract contract ERC721Pausable is ERC721, Pausable { + /** + * @dev See {ERC721-_update}. + * + * Requirements: + * + * - the contract must not be paused. + */ + function _update( + address to, + uint256 tokenId, + address auth + ) internal virtual override whenNotPaused returns (address) { + return super._update(to, tokenId, auth); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/token/ERC721/extensions/ERC721Royalty.sol b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC721/extensions/ERC721Royalty.sol new file mode 100644 index 00000000..cb51fdb7 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC721/extensions/ERC721Royalty.sol @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC721/extensions/ERC721Royalty.sol) + +pragma solidity ^0.8.20; + +import {ERC721} from "../ERC721.sol"; +import {IERC165} from "../../../utils/introspection/ERC165.sol"; +import {ERC2981} from "../../common/ERC2981.sol"; + +/** + * @dev Extension of ERC-721 with the ERC-2981 NFT Royalty Standard, a standardized way to retrieve royalty payment + * information. + * + * Royalty information can be specified globally for all token ids via {ERC2981-_setDefaultRoyalty}, and/or individually + * for specific token ids via {ERC2981-_setTokenRoyalty}. The latter takes precedence over the first. + * + * IMPORTANT: ERC-2981 only specifies a way to signal royalty information and does not enforce its payment. See + * https://eips.ethereum.org/EIPS/eip-2981#optional-royalty-payments[Rationale] in the ERC. Marketplaces are expected to + * voluntarily pay royalties together with sales, but note that this standard is not yet widely supported. + */ +abstract contract ERC721Royalty is ERC2981, ERC721 { + /// @inheritdoc IERC165 + function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721, ERC2981) returns (bool) { + return super.supportsInterface(interfaceId); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/token/ERC721/extensions/ERC721URIStorage.sol b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC721/extensions/ERC721URIStorage.sol new file mode 100644 index 00000000..99630df8 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC721/extensions/ERC721URIStorage.sol @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC721/extensions/ERC721URIStorage.sol) + +pragma solidity ^0.8.20; + +import {ERC721} from "../ERC721.sol"; +import {IERC721Metadata} from "./IERC721Metadata.sol"; +import {Strings} from "../../../utils/Strings.sol"; +import {IERC4906} from "../../../interfaces/IERC4906.sol"; +import {IERC165} from "../../../interfaces/IERC165.sol"; + +/** + * @dev ERC-721 token with storage based token URI management. + */ +abstract contract ERC721URIStorage is IERC4906, ERC721 { + using Strings for uint256; + + // Interface ID as defined in ERC-4906. This does not correspond to a traditional interface ID as ERC-4906 only + // defines events and does not include any external function. + bytes4 private constant ERC4906_INTERFACE_ID = bytes4(0x49064906); + + // Optional mapping for token URIs + mapping(uint256 tokenId => string) private _tokenURIs; + + /// @inheritdoc IERC165 + function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721, IERC165) returns (bool) { + return interfaceId == ERC4906_INTERFACE_ID || super.supportsInterface(interfaceId); + } + + /// @inheritdoc IERC721Metadata + function tokenURI(uint256 tokenId) public view virtual override returns (string memory) { + _requireOwned(tokenId); + + string memory _tokenURI = _tokenURIs[tokenId]; + string memory base = _baseURI(); + + // If there is no base URI, return the token URI. + if (bytes(base).length == 0) { + return _tokenURI; + } + // If both are set, concatenate the baseURI and tokenURI (via string.concat). + if (bytes(_tokenURI).length > 0) { + return string.concat(base, _tokenURI); + } + + return super.tokenURI(tokenId); + } + + /** + * @dev Sets `_tokenURI` as the tokenURI of `tokenId`. + * + * Emits {IERC4906-MetadataUpdate}. + */ + function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual { + _tokenURIs[tokenId] = _tokenURI; + emit MetadataUpdate(tokenId); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/token/ERC721/extensions/ERC721Votes.sol b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC721/extensions/ERC721Votes.sol new file mode 100644 index 00000000..f71195ce --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC721/extensions/ERC721Votes.sol @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/extensions/ERC721Votes.sol) + +pragma solidity ^0.8.20; + +import {ERC721} from "../ERC721.sol"; +import {Votes} from "../../../governance/utils/Votes.sol"; + +/** + * @dev Extension of ERC-721 to support voting and delegation as implemented by {Votes}, where each individual NFT counts + * as 1 vote unit. + * + * Tokens do not count as votes until they are delegated, because votes must be tracked which incurs an additional cost + * on every transfer. Token holders can either delegate to a trusted representative who will decide how to make use of + * the votes in governance decisions, or they can delegate to themselves to be their own representative. + */ +abstract contract ERC721Votes is ERC721, Votes { + /** + * @dev See {ERC721-_update}. Adjusts votes when tokens are transferred. + * + * Emits a {IVotes-DelegateVotesChanged} event. + */ + function _update(address to, uint256 tokenId, address auth) internal virtual override returns (address) { + address previousOwner = super._update(to, tokenId, auth); + + _transferVotingUnits(previousOwner, to, 1); + + return previousOwner; + } + + /** + * @dev Returns the balance of `account`. + * + * WARNING: Overriding this function will likely result in incorrect vote tracking. + */ + function _getVotingUnits(address account) internal view virtual override returns (uint256) { + return balanceOf(account); + } + + /** + * @dev See {ERC721-_increaseBalance}. We need that to account tokens that were minted in batch. + */ + function _increaseBalance(address account, uint128 amount) internal virtual override { + super._increaseBalance(account, amount); + _transferVotingUnits(address(0), account, amount); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/token/ERC721/extensions/ERC721Wrapper.sol b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC721/extensions/ERC721Wrapper.sol new file mode 100644 index 00000000..111136bb --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC721/extensions/ERC721Wrapper.sol @@ -0,0 +1,102 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/extensions/ERC721Wrapper.sol) + +pragma solidity ^0.8.20; + +import {IERC721, ERC721} from "../ERC721.sol"; +import {IERC721Receiver} from "../IERC721Receiver.sol"; + +/** + * @dev Extension of the ERC-721 token contract to support token wrapping. + * + * Users can deposit and withdraw an "underlying token" and receive a "wrapped token" with a matching tokenId. This is + * useful in conjunction with other modules. For example, combining this wrapping mechanism with {ERC721Votes} will allow + * the wrapping of an existing "basic" ERC-721 into a governance token. + */ +abstract contract ERC721Wrapper is ERC721, IERC721Receiver { + IERC721 private immutable _underlying; + + /** + * @dev The received ERC-721 token couldn't be wrapped. + */ + error ERC721UnsupportedToken(address token); + + constructor(IERC721 underlyingToken) { + _underlying = underlyingToken; + } + + /** + * @dev Allow a user to deposit underlying tokens and mint the corresponding tokenIds. + */ + function depositFor(address account, uint256[] memory tokenIds) public virtual returns (bool) { + uint256 length = tokenIds.length; + for (uint256 i = 0; i < length; ++i) { + uint256 tokenId = tokenIds[i]; + + // This is an "unsafe" transfer that doesn't call any hook on the receiver. With underlying() being trusted + // (by design of this contract) and no other contracts expected to be called from there, we are safe. + // slither-disable-next-line reentrancy-no-eth + underlying().transferFrom(_msgSender(), address(this), tokenId); + _safeMint(account, tokenId); + } + + return true; + } + + /** + * @dev Allow a user to burn wrapped tokens and withdraw the corresponding tokenIds of the underlying tokens. + */ + function withdrawTo(address account, uint256[] memory tokenIds) public virtual returns (bool) { + uint256 length = tokenIds.length; + for (uint256 i = 0; i < length; ++i) { + uint256 tokenId = tokenIds[i]; + // Setting an "auth" arguments enables the `_isAuthorized` check which verifies that the token exists + // (from != 0). Therefore, it is not needed to verify that the return value is not 0 here. + _update(address(0), tokenId, _msgSender()); + // Checks were already performed at this point, and there's no way to retake ownership or approval from + // the wrapped tokenId after this point, so it's safe to remove the reentrancy check for the next line. + // slither-disable-next-line reentrancy-no-eth + underlying().safeTransferFrom(address(this), account, tokenId); + } + + return true; + } + + /** + * @dev Overrides {IERC721Receiver-onERC721Received} to allow minting on direct ERC-721 transfers to + * this contract. + * + * In case there's data attached, it validates that the operator is this contract, so only trusted data + * is accepted from {depositFor}. + * + * WARNING: Doesn't work with unsafe transfers (eg. {IERC721-transferFrom}). Use {ERC721Wrapper-_recover} + * for recovering in that scenario. + */ + function onERC721Received(address, address from, uint256 tokenId, bytes memory) public virtual returns (bytes4) { + if (address(underlying()) != _msgSender()) { + revert ERC721UnsupportedToken(_msgSender()); + } + _safeMint(from, tokenId); + return IERC721Receiver.onERC721Received.selector; + } + + /** + * @dev Mint a wrapped token to cover any underlyingToken that would have been transferred by mistake. Internal + * function that can be exposed with access control if desired. + */ + function _recover(address account, uint256 tokenId) internal virtual returns (uint256) { + address owner = underlying().ownerOf(tokenId); + if (owner != address(this)) { + revert ERC721IncorrectOwner(address(this), tokenId, owner); + } + _safeMint(account, tokenId); + return tokenId; + } + + /** + * @dev Returns the underlying token. + */ + function underlying() public view virtual returns (IERC721) { + return _underlying; + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/token/ERC721/extensions/IERC721Enumerable.sol b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC721/extensions/IERC721Enumerable.sol new file mode 100644 index 00000000..1fe58854 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC721/extensions/IERC721Enumerable.sol @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC721/extensions/IERC721Enumerable.sol) + +pragma solidity >=0.6.2; + +import {IERC721} from "../IERC721.sol"; + +/** + * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension + * @dev See https://eips.ethereum.org/EIPS/eip-721 + */ +interface IERC721Enumerable is IERC721 { + /** + * @dev Returns the total amount of tokens stored by the contract. + */ + function totalSupply() external view returns (uint256); + + /** + * @dev Returns a token ID owned by `owner` at a given `index` of its token list. + * Use along with {balanceOf} to enumerate all of ``owner``'s tokens. + */ + function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256); + + /** + * @dev Returns a token ID at a given `index` of all the tokens stored by the contract. + * Use along with {totalSupply} to enumerate all tokens. + */ + function tokenByIndex(uint256 index) external view returns (uint256); +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/token/ERC721/extensions/IERC721Metadata.sol b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC721/extensions/IERC721Metadata.sol new file mode 100644 index 00000000..b4da16df --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC721/extensions/IERC721Metadata.sol @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC721/extensions/IERC721Metadata.sol) + +pragma solidity >=0.6.2; + +import {IERC721} from "../IERC721.sol"; + +/** + * @title ERC-721 Non-Fungible Token Standard, optional metadata extension + * @dev See https://eips.ethereum.org/EIPS/eip-721 + */ +interface IERC721Metadata is IERC721 { + /** + * @dev Returns the token collection name. + */ + function name() external view returns (string memory); + + /** + * @dev Returns the token collection symbol. + */ + function symbol() external view returns (string memory); + + /** + * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token. + */ + function tokenURI(uint256 tokenId) external view returns (string memory); +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/token/ERC721/utils/ERC721Holder.sol b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC721/utils/ERC721Holder.sol new file mode 100644 index 00000000..6bb23ace --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC721/utils/ERC721Holder.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/utils/ERC721Holder.sol) + +pragma solidity ^0.8.20; + +import {IERC721Receiver} from "../IERC721Receiver.sol"; + +/** + * @dev Implementation of the {IERC721Receiver} interface. + * + * Accepts all token transfers. + * Make sure the contract is able to use its token with {IERC721-safeTransferFrom}, {IERC721-approve} or + * {IERC721-setApprovalForAll}. + */ +abstract contract ERC721Holder is IERC721Receiver { + /** + * @dev See {IERC721Receiver-onERC721Received}. + * + * Always returns `IERC721Receiver.onERC721Received.selector`. + */ + function onERC721Received(address, address, uint256, bytes memory) public virtual returns (bytes4) { + return this.onERC721Received.selector; + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/token/ERC721/utils/ERC721Utils.sol b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC721/utils/ERC721Utils.sol new file mode 100644 index 00000000..575ee8bd --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/token/ERC721/utils/ERC721Utils.sol @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC721/utils/ERC721Utils.sol) + +pragma solidity ^0.8.20; + +import {IERC721Receiver} from "../IERC721Receiver.sol"; +import {IERC721Errors} from "../../../interfaces/draft-IERC6093.sol"; + +/** + * @dev Library that provide common ERC-721 utility functions. + * + * See https://eips.ethereum.org/EIPS/eip-721[ERC-721]. + * + * _Available since v5.1._ + */ +library ERC721Utils { + /** + * @dev Performs an acceptance check for the provided `operator` by calling {IERC721Receiver-onERC721Received} + * on the `to` address. The `operator` is generally the address that initiated the token transfer (i.e. `msg.sender`). + * + * The acceptance call is not executed and treated as a no-op if the target address doesn't contain code (i.e. an EOA). + * Otherwise, the recipient must implement {IERC721Receiver-onERC721Received} and return the acceptance magic value to accept + * the transfer. + */ + function checkOnERC721Received( + address operator, + address from, + address to, + uint256 tokenId, + bytes memory data + ) internal { + if (to.code.length > 0) { + try IERC721Receiver(to).onERC721Received(operator, from, tokenId, data) returns (bytes4 retval) { + if (retval != IERC721Receiver.onERC721Received.selector) { + // Token rejected + revert IERC721Errors.ERC721InvalidReceiver(to); + } + } catch (bytes memory reason) { + if (reason.length == 0) { + // non-IERC721Receiver implementer + revert IERC721Errors.ERC721InvalidReceiver(to); + } else { + assembly ("memory-safe") { + revert(add(reason, 0x20), mload(reason)) + } + } + } + } + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/token/common/ERC2981.sol b/dependencies/@openzeppelin-contracts-5.4.0/token/common/ERC2981.sol new file mode 100644 index 00000000..5d75e3aa --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/token/common/ERC2981.sol @@ -0,0 +1,139 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (token/common/ERC2981.sol) + +pragma solidity ^0.8.20; + +import {IERC2981} from "../../interfaces/IERC2981.sol"; +import {IERC165, ERC165} from "../../utils/introspection/ERC165.sol"; + +/** + * @dev Implementation of the NFT Royalty Standard, a standardized way to retrieve royalty payment information. + * + * Royalty information can be specified globally for all token ids via {_setDefaultRoyalty}, and/or individually for + * specific token ids via {_setTokenRoyalty}. The latter takes precedence over the first. + * + * Royalty is specified as a fraction of sale price. {_feeDenominator} is overridable but defaults to 10000, meaning the + * fee is specified in basis points by default. + * + * IMPORTANT: ERC-2981 only specifies a way to signal royalty information and does not enforce its payment. See + * https://eips.ethereum.org/EIPS/eip-2981#optional-royalty-payments[Rationale] in the ERC. Marketplaces are expected to + * voluntarily pay royalties together with sales, but note that this standard is not yet widely supported. + */ +abstract contract ERC2981 is IERC2981, ERC165 { + struct RoyaltyInfo { + address receiver; + uint96 royaltyFraction; + } + + RoyaltyInfo private _defaultRoyaltyInfo; + mapping(uint256 tokenId => RoyaltyInfo) private _tokenRoyaltyInfo; + + /** + * @dev The default royalty set is invalid (eg. (numerator / denominator) >= 1). + */ + error ERC2981InvalidDefaultRoyalty(uint256 numerator, uint256 denominator); + + /** + * @dev The default royalty receiver is invalid. + */ + error ERC2981InvalidDefaultRoyaltyReceiver(address receiver); + + /** + * @dev The royalty set for a specific `tokenId` is invalid (eg. (numerator / denominator) >= 1). + */ + error ERC2981InvalidTokenRoyalty(uint256 tokenId, uint256 numerator, uint256 denominator); + + /** + * @dev The royalty receiver for `tokenId` is invalid. + */ + error ERC2981InvalidTokenRoyaltyReceiver(uint256 tokenId, address receiver); + + /// @inheritdoc IERC165 + function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) { + return interfaceId == type(IERC2981).interfaceId || super.supportsInterface(interfaceId); + } + + /// @inheritdoc IERC2981 + function royaltyInfo( + uint256 tokenId, + uint256 salePrice + ) public view virtual returns (address receiver, uint256 amount) { + RoyaltyInfo storage _royaltyInfo = _tokenRoyaltyInfo[tokenId]; + address royaltyReceiver = _royaltyInfo.receiver; + uint96 royaltyFraction = _royaltyInfo.royaltyFraction; + + if (royaltyReceiver == address(0)) { + royaltyReceiver = _defaultRoyaltyInfo.receiver; + royaltyFraction = _defaultRoyaltyInfo.royaltyFraction; + } + + uint256 royaltyAmount = (salePrice * royaltyFraction) / _feeDenominator(); + + return (royaltyReceiver, royaltyAmount); + } + + /** + * @dev The denominator with which to interpret the fee set in {_setTokenRoyalty} and {_setDefaultRoyalty} as a + * fraction of the sale price. Defaults to 10000 so fees are expressed in basis points, but may be customized by an + * override. + */ + function _feeDenominator() internal pure virtual returns (uint96) { + return 10000; + } + + /** + * @dev Sets the royalty information that all ids in this contract will default to. + * + * Requirements: + * + * - `receiver` cannot be the zero address. + * - `feeNumerator` cannot be greater than the fee denominator. + */ + function _setDefaultRoyalty(address receiver, uint96 feeNumerator) internal virtual { + uint256 denominator = _feeDenominator(); + if (feeNumerator > denominator) { + // Royalty fee will exceed the sale price + revert ERC2981InvalidDefaultRoyalty(feeNumerator, denominator); + } + if (receiver == address(0)) { + revert ERC2981InvalidDefaultRoyaltyReceiver(address(0)); + } + + _defaultRoyaltyInfo = RoyaltyInfo(receiver, feeNumerator); + } + + /** + * @dev Removes default royalty information. + */ + function _deleteDefaultRoyalty() internal virtual { + delete _defaultRoyaltyInfo; + } + + /** + * @dev Sets the royalty information for a specific token id, overriding the global default. + * + * Requirements: + * + * - `receiver` cannot be the zero address. + * - `feeNumerator` cannot be greater than the fee denominator. + */ + function _setTokenRoyalty(uint256 tokenId, address receiver, uint96 feeNumerator) internal virtual { + uint256 denominator = _feeDenominator(); + if (feeNumerator > denominator) { + // Royalty fee will exceed the sale price + revert ERC2981InvalidTokenRoyalty(tokenId, feeNumerator, denominator); + } + if (receiver == address(0)) { + revert ERC2981InvalidTokenRoyaltyReceiver(tokenId, address(0)); + } + + _tokenRoyaltyInfo[tokenId] = RoyaltyInfo(receiver, feeNumerator); + } + + /** + * @dev Resets royalty information for the token id back to the global default. + */ + function _resetTokenRoyalty(uint256 tokenId) internal virtual { + delete _tokenRoyaltyInfo[tokenId]; + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/utils/Address.sol b/dependencies/@openzeppelin-contracts-5.4.0/utils/Address.sol new file mode 100644 index 00000000..cb90227d --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/utils/Address.sol @@ -0,0 +1,149 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (utils/Address.sol) + +pragma solidity ^0.8.20; + +import {Errors} from "./Errors.sol"; + +/** + * @dev Collection of functions related to the address type + */ +library Address { + /** + * @dev There's no code at `target` (it is not a contract). + */ + error AddressEmptyCode(address target); + + /** + * @dev Replacement for Solidity's `transfer`: sends `amount` wei to + * `recipient`, forwarding all available gas and reverting on errors. + * + * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost + * of certain opcodes, possibly making contracts go over the 2300 gas limit + * imposed by `transfer`, making them unable to receive funds via + * `transfer`. {sendValue} removes this limitation. + * + * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. + * + * IMPORTANT: because control is transferred to `recipient`, care must be + * taken to not create reentrancy vulnerabilities. Consider using + * {ReentrancyGuard} or the + * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. + */ + function sendValue(address payable recipient, uint256 amount) internal { + if (address(this).balance < amount) { + revert Errors.InsufficientBalance(address(this).balance, amount); + } + + (bool success, bytes memory returndata) = recipient.call{value: amount}(""); + if (!success) { + _revert(returndata); + } + } + + /** + * @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 or custom error, it is bubbled + * up by this function (like regular Solidity function calls). However, if + * the call reverted with no returned reason, this function reverts with a + * {Errors.FailedCall} error. + * + * 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. + */ + function functionCall(address target, bytes memory data) internal returns (bytes memory) { + return functionCallWithValue(target, data, 0); + } + + /** + * @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`. + */ + function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { + if (address(this).balance < value) { + revert Errors.InsufficientBalance(address(this).balance, value); + } + (bool success, bytes memory returndata) = target.call{value: value}(data); + return verifyCallResultFromTarget(target, success, returndata); + } + + /** + * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], + * but performing a static call. + */ + function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { + (bool success, bytes memory returndata) = target.staticcall(data); + return verifyCallResultFromTarget(target, success, returndata); + } + + /** + * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], + * but performing a delegate call. + */ + function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { + (bool success, bytes memory returndata) = target.delegatecall(data); + return verifyCallResultFromTarget(target, success, returndata); + } + + /** + * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target + * was not a contract or bubbling up the revert reason (falling back to {Errors.FailedCall}) in case + * of an unsuccessful call. + */ + function verifyCallResultFromTarget( + address target, + bool success, + bytes memory returndata + ) internal view returns (bytes memory) { + if (!success) { + _revert(returndata); + } else { + // only check if target is a contract if the call was successful and the return data is empty + // otherwise we already know that it was a contract + if (returndata.length == 0 && target.code.length == 0) { + revert AddressEmptyCode(target); + } + return returndata; + } + } + + /** + * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the + * revert reason or with a default {Errors.FailedCall} error. + */ + function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) { + if (!success) { + _revert(returndata); + } else { + return returndata; + } + } + + /** + * @dev Reverts with returndata if present. Otherwise reverts with {Errors.FailedCall}. + */ + function _revert(bytes memory returndata) private pure { + // Look for revert reason and bubble it up if present + if (returndata.length > 0) { + // The easiest way to bubble the revert reason is using memory via assembly + assembly ("memory-safe") { + revert(add(returndata, 0x20), mload(returndata)) + } + } else { + revert Errors.FailedCall(); + } + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/utils/Arrays.sol b/dependencies/@openzeppelin-contracts-5.4.0/utils/Arrays.sol new file mode 100644 index 00000000..511354a5 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/utils/Arrays.sol @@ -0,0 +1,552 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (utils/Arrays.sol) +// This file was procedurally generated from scripts/generate/templates/Arrays.js. + +pragma solidity ^0.8.20; + +import {Comparators} from "./Comparators.sol"; +import {SlotDerivation} from "./SlotDerivation.sol"; +import {StorageSlot} from "./StorageSlot.sol"; +import {Math} from "./math/Math.sol"; + +/** + * @dev Collection of functions related to array types. + */ +library Arrays { + using SlotDerivation for bytes32; + using StorageSlot for bytes32; + + /** + * @dev Sort an array of uint256 (in memory) following the provided comparator function. + * + * This function does the sorting "in place", meaning that it overrides the input. The object is returned for + * convenience, but that returned value can be discarded safely if the caller has a memory pointer to the array. + * + * NOTE: this function's cost is `O(n · log(n))` in average and `O(n²)` in the worst case, with n the length of the + * array. Using it in view functions that are executed through `eth_call` is safe, but one should be very careful + * when executing this as part of a transaction. If the array being sorted is too large, the sort operation may + * consume more gas than is available in a block, leading to potential DoS. + * + * IMPORTANT: Consider memory side-effects when using custom comparator functions that access memory in an unsafe way. + */ + function sort( + uint256[] memory array, + function(uint256, uint256) pure returns (bool) comp + ) internal pure returns (uint256[] memory) { + _quickSort(_begin(array), _end(array), comp); + return array; + } + + /** + * @dev Variant of {sort} that sorts an array of uint256 in increasing order. + */ + function sort(uint256[] memory array) internal pure returns (uint256[] memory) { + sort(array, Comparators.lt); + return array; + } + + /** + * @dev Sort an array of address (in memory) following the provided comparator function. + * + * This function does the sorting "in place", meaning that it overrides the input. The object is returned for + * convenience, but that returned value can be discarded safely if the caller has a memory pointer to the array. + * + * NOTE: this function's cost is `O(n · log(n))` in average and `O(n²)` in the worst case, with n the length of the + * array. Using it in view functions that are executed through `eth_call` is safe, but one should be very careful + * when executing this as part of a transaction. If the array being sorted is too large, the sort operation may + * consume more gas than is available in a block, leading to potential DoS. + * + * IMPORTANT: Consider memory side-effects when using custom comparator functions that access memory in an unsafe way. + */ + function sort( + address[] memory array, + function(address, address) pure returns (bool) comp + ) internal pure returns (address[] memory) { + sort(_castToUint256Array(array), _castToUint256Comp(comp)); + return array; + } + + /** + * @dev Variant of {sort} that sorts an array of address in increasing order. + */ + function sort(address[] memory array) internal pure returns (address[] memory) { + sort(_castToUint256Array(array), Comparators.lt); + return array; + } + + /** + * @dev Sort an array of bytes32 (in memory) following the provided comparator function. + * + * This function does the sorting "in place", meaning that it overrides the input. The object is returned for + * convenience, but that returned value can be discarded safely if the caller has a memory pointer to the array. + * + * NOTE: this function's cost is `O(n · log(n))` in average and `O(n²)` in the worst case, with n the length of the + * array. Using it in view functions that are executed through `eth_call` is safe, but one should be very careful + * when executing this as part of a transaction. If the array being sorted is too large, the sort operation may + * consume more gas than is available in a block, leading to potential DoS. + * + * IMPORTANT: Consider memory side-effects when using custom comparator functions that access memory in an unsafe way. + */ + function sort( + bytes32[] memory array, + function(bytes32, bytes32) pure returns (bool) comp + ) internal pure returns (bytes32[] memory) { + sort(_castToUint256Array(array), _castToUint256Comp(comp)); + return array; + } + + /** + * @dev Variant of {sort} that sorts an array of bytes32 in increasing order. + */ + function sort(bytes32[] memory array) internal pure returns (bytes32[] memory) { + sort(_castToUint256Array(array), Comparators.lt); + return array; + } + + /** + * @dev Performs a quick sort of a segment of memory. The segment sorted starts at `begin` (inclusive), and stops + * at end (exclusive). Sorting follows the `comp` comparator. + * + * Invariant: `begin <= end`. This is the case when initially called by {sort} and is preserved in subcalls. + * + * IMPORTANT: Memory locations between `begin` and `end` are not validated/zeroed. This function should + * be used only if the limits are within a memory array. + */ + function _quickSort(uint256 begin, uint256 end, function(uint256, uint256) pure returns (bool) comp) private pure { + unchecked { + if (end - begin < 0x40) return; + + // Use first element as pivot + uint256 pivot = _mload(begin); + // Position where the pivot should be at the end of the loop + uint256 pos = begin; + + for (uint256 it = begin + 0x20; it < end; it += 0x20) { + if (comp(_mload(it), pivot)) { + // If the value stored at the iterator's position comes before the pivot, we increment the + // position of the pivot and move the value there. + pos += 0x20; + _swap(pos, it); + } + } + + _swap(begin, pos); // Swap pivot into place + _quickSort(begin, pos, comp); // Sort the left side of the pivot + _quickSort(pos + 0x20, end, comp); // Sort the right side of the pivot + } + } + + /** + * @dev Pointer to the memory location of the first element of `array`. + */ + function _begin(uint256[] memory array) private pure returns (uint256 ptr) { + assembly ("memory-safe") { + ptr := add(array, 0x20) + } + } + + /** + * @dev Pointer to the memory location of the first memory word (32bytes) after `array`. This is the memory word + * that comes just after the last element of the array. + */ + function _end(uint256[] memory array) private pure returns (uint256 ptr) { + unchecked { + return _begin(array) + array.length * 0x20; + } + } + + /** + * @dev Load memory word (as a uint256) at location `ptr`. + */ + function _mload(uint256 ptr) private pure returns (uint256 value) { + assembly { + value := mload(ptr) + } + } + + /** + * @dev Swaps the elements memory location `ptr1` and `ptr2`. + */ + function _swap(uint256 ptr1, uint256 ptr2) private pure { + assembly { + let value1 := mload(ptr1) + let value2 := mload(ptr2) + mstore(ptr1, value2) + mstore(ptr2, value1) + } + } + + /// @dev Helper: low level cast address memory array to uint256 memory array + function _castToUint256Array(address[] memory input) private pure returns (uint256[] memory output) { + assembly { + output := input + } + } + + /// @dev Helper: low level cast bytes32 memory array to uint256 memory array + function _castToUint256Array(bytes32[] memory input) private pure returns (uint256[] memory output) { + assembly { + output := input + } + } + + /// @dev Helper: low level cast address comp function to uint256 comp function + function _castToUint256Comp( + function(address, address) pure returns (bool) input + ) private pure returns (function(uint256, uint256) pure returns (bool) output) { + assembly { + output := input + } + } + + /// @dev Helper: low level cast bytes32 comp function to uint256 comp function + function _castToUint256Comp( + function(bytes32, bytes32) pure returns (bool) input + ) private pure returns (function(uint256, uint256) pure returns (bool) output) { + assembly { + output := input + } + } + + /** + * @dev Searches a sorted `array` and returns the first index that contains + * a value greater or equal to `element`. If no such index exists (i.e. all + * values in the array are strictly less than `element`), the array length is + * returned. Time complexity O(log n). + * + * NOTE: The `array` is expected to be sorted in ascending order, and to + * contain no repeated elements. + * + * IMPORTANT: Deprecated. This implementation behaves as {lowerBound} but lacks + * support for repeated elements in the array. The {lowerBound} function should + * be used instead. + */ + function findUpperBound(uint256[] storage array, uint256 element) internal view returns (uint256) { + uint256 low = 0; + uint256 high = array.length; + + if (high == 0) { + return 0; + } + + while (low < high) { + uint256 mid = Math.average(low, high); + + // Note that mid will always be strictly less than high (i.e. it will be a valid array index) + // because Math.average rounds towards zero (it does integer division with truncation). + if (unsafeAccess(array, mid).value > element) { + high = mid; + } else { + low = mid + 1; + } + } + + // At this point `low` is the exclusive upper bound. We will return the inclusive upper bound. + if (low > 0 && unsafeAccess(array, low - 1).value == element) { + return low - 1; + } else { + return low; + } + } + + /** + * @dev Searches an `array` sorted in ascending order and returns the first + * index that contains a value greater or equal than `element`. If no such index + * exists (i.e. all values in the array are strictly less than `element`), the array + * length is returned. Time complexity O(log n). + * + * See C++'s https://en.cppreference.com/w/cpp/algorithm/lower_bound[lower_bound]. + */ + function lowerBound(uint256[] storage array, uint256 element) internal view returns (uint256) { + uint256 low = 0; + uint256 high = array.length; + + if (high == 0) { + return 0; + } + + while (low < high) { + uint256 mid = Math.average(low, high); + + // Note that mid will always be strictly less than high (i.e. it will be a valid array index) + // because Math.average rounds towards zero (it does integer division with truncation). + if (unsafeAccess(array, mid).value < element) { + // this cannot overflow because mid < high + unchecked { + low = mid + 1; + } + } else { + high = mid; + } + } + + return low; + } + + /** + * @dev Searches an `array` sorted in ascending order and returns the first + * index that contains a value strictly greater than `element`. If no such index + * exists (i.e. all values in the array are strictly less than `element`), the array + * length is returned. Time complexity O(log n). + * + * See C++'s https://en.cppreference.com/w/cpp/algorithm/upper_bound[upper_bound]. + */ + function upperBound(uint256[] storage array, uint256 element) internal view returns (uint256) { + uint256 low = 0; + uint256 high = array.length; + + if (high == 0) { + return 0; + } + + while (low < high) { + uint256 mid = Math.average(low, high); + + // Note that mid will always be strictly less than high (i.e. it will be a valid array index) + // because Math.average rounds towards zero (it does integer division with truncation). + if (unsafeAccess(array, mid).value > element) { + high = mid; + } else { + // this cannot overflow because mid < high + unchecked { + low = mid + 1; + } + } + } + + return low; + } + + /** + * @dev Same as {lowerBound}, but with an array in memory. + */ + function lowerBoundMemory(uint256[] memory array, uint256 element) internal pure returns (uint256) { + uint256 low = 0; + uint256 high = array.length; + + if (high == 0) { + return 0; + } + + while (low < high) { + uint256 mid = Math.average(low, high); + + // Note that mid will always be strictly less than high (i.e. it will be a valid array index) + // because Math.average rounds towards zero (it does integer division with truncation). + if (unsafeMemoryAccess(array, mid) < element) { + // this cannot overflow because mid < high + unchecked { + low = mid + 1; + } + } else { + high = mid; + } + } + + return low; + } + + /** + * @dev Same as {upperBound}, but with an array in memory. + */ + function upperBoundMemory(uint256[] memory array, uint256 element) internal pure returns (uint256) { + uint256 low = 0; + uint256 high = array.length; + + if (high == 0) { + return 0; + } + + while (low < high) { + uint256 mid = Math.average(low, high); + + // Note that mid will always be strictly less than high (i.e. it will be a valid array index) + // because Math.average rounds towards zero (it does integer division with truncation). + if (unsafeMemoryAccess(array, mid) > element) { + high = mid; + } else { + // this cannot overflow because mid < high + unchecked { + low = mid + 1; + } + } + } + + return low; + } + + /** + * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check. + * + * WARNING: Only use if you are certain `pos` is lower than the array length. + */ + function unsafeAccess(address[] storage arr, uint256 pos) internal pure returns (StorageSlot.AddressSlot storage) { + bytes32 slot; + assembly ("memory-safe") { + slot := arr.slot + } + return slot.deriveArray().offset(pos).getAddressSlot(); + } + + /** + * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check. + * + * WARNING: Only use if you are certain `pos` is lower than the array length. + */ + function unsafeAccess(bytes32[] storage arr, uint256 pos) internal pure returns (StorageSlot.Bytes32Slot storage) { + bytes32 slot; + assembly ("memory-safe") { + slot := arr.slot + } + return slot.deriveArray().offset(pos).getBytes32Slot(); + } + + /** + * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check. + * + * WARNING: Only use if you are certain `pos` is lower than the array length. + */ + function unsafeAccess(uint256[] storage arr, uint256 pos) internal pure returns (StorageSlot.Uint256Slot storage) { + bytes32 slot; + assembly ("memory-safe") { + slot := arr.slot + } + return slot.deriveArray().offset(pos).getUint256Slot(); + } + + /** + * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check. + * + * WARNING: Only use if you are certain `pos` is lower than the array length. + */ + function unsafeAccess(bytes[] storage arr, uint256 pos) internal pure returns (StorageSlot.BytesSlot storage) { + bytes32 slot; + assembly ("memory-safe") { + slot := arr.slot + } + return slot.deriveArray().offset(pos).getBytesSlot(); + } + + /** + * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check. + * + * WARNING: Only use if you are certain `pos` is lower than the array length. + */ + function unsafeAccess(string[] storage arr, uint256 pos) internal pure returns (StorageSlot.StringSlot storage) { + bytes32 slot; + assembly ("memory-safe") { + slot := arr.slot + } + return slot.deriveArray().offset(pos).getStringSlot(); + } + + /** + * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check. + * + * WARNING: Only use if you are certain `pos` is lower than the array length. + */ + function unsafeMemoryAccess(address[] memory arr, uint256 pos) internal pure returns (address res) { + assembly { + res := mload(add(add(arr, 0x20), mul(pos, 0x20))) + } + } + + /** + * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check. + * + * WARNING: Only use if you are certain `pos` is lower than the array length. + */ + function unsafeMemoryAccess(bytes32[] memory arr, uint256 pos) internal pure returns (bytes32 res) { + assembly { + res := mload(add(add(arr, 0x20), mul(pos, 0x20))) + } + } + + /** + * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check. + * + * WARNING: Only use if you are certain `pos` is lower than the array length. + */ + function unsafeMemoryAccess(uint256[] memory arr, uint256 pos) internal pure returns (uint256 res) { + assembly { + res := mload(add(add(arr, 0x20), mul(pos, 0x20))) + } + } + + /** + * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check. + * + * WARNING: Only use if you are certain `pos` is lower than the array length. + */ + function unsafeMemoryAccess(bytes[] memory arr, uint256 pos) internal pure returns (bytes memory res) { + assembly { + res := mload(add(add(arr, 0x20), mul(pos, 0x20))) + } + } + + /** + * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check. + * + * WARNING: Only use if you are certain `pos` is lower than the array length. + */ + function unsafeMemoryAccess(string[] memory arr, uint256 pos) internal pure returns (string memory res) { + assembly { + res := mload(add(add(arr, 0x20), mul(pos, 0x20))) + } + } + + /** + * @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. + */ + function unsafeSetLength(address[] storage array, uint256 len) internal { + assembly ("memory-safe") { + sstore(array.slot, len) + } + } + + /** + * @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. + */ + function unsafeSetLength(bytes32[] storage array, uint256 len) internal { + assembly ("memory-safe") { + sstore(array.slot, len) + } + } + + /** + * @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. + */ + function unsafeSetLength(uint256[] storage array, uint256 len) internal { + assembly ("memory-safe") { + sstore(array.slot, len) + } + } + + /** + * @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. + */ + function unsafeSetLength(bytes[] storage array, uint256 len) internal { + assembly ("memory-safe") { + sstore(array.slot, len) + } + } + + /** + * @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. + */ + function unsafeSetLength(string[] storage array, uint256 len) internal { + assembly ("memory-safe") { + sstore(array.slot, len) + } + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/utils/Base64.sol b/dependencies/@openzeppelin-contracts-5.4.0/utils/Base64.sol new file mode 100644 index 00000000..d9b09ec0 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/utils/Base64.sol @@ -0,0 +1,119 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (utils/Base64.sol) + +pragma solidity ^0.8.20; + +/** + * @dev Provides a set of functions to operate with Base64 strings. + */ +library Base64 { + /** + * @dev Base64 Encoding/Decoding Table + * See sections 4 and 5 of https://datatracker.ietf.org/doc/html/rfc4648 + */ + string internal constant _TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + string internal constant _TABLE_URL = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; + + /** + * @dev Converts a `bytes` to its Bytes64 `string` representation. + */ + function encode(bytes memory data) internal pure returns (string memory) { + return _encode(data, _TABLE, true); + } + + /** + * @dev Converts a `bytes` to its Bytes64Url `string` representation. + * Output is not padded with `=` as specified in https://www.rfc-editor.org/rfc/rfc4648[rfc4648]. + */ + function encodeURL(bytes memory data) internal pure returns (string memory) { + return _encode(data, _TABLE_URL, false); + } + + /** + * @dev Internal table-agnostic conversion + */ + function _encode(bytes memory data, string memory table, bool withPadding) private pure returns (string memory) { + /** + * Inspired by Brecht Devos (Brechtpd) implementation - MIT licence + * https://github.com/Brechtpd/base64/blob/e78d9fd951e7b0977ddca77d92dc85183770daf4/base64.sol + */ + if (data.length == 0) return ""; + + // If padding is enabled, the final length should be `bytes` data length divided by 3 rounded up and then + // multiplied by 4 so that it leaves room for padding the last chunk + // - `data.length + 2` -> Prepare for division rounding up + // - `/ 3` -> Number of 3-bytes chunks (rounded up) + // - `4 *` -> 4 characters for each chunk + // This is equivalent to: 4 * Math.ceil(data.length / 3) + // + // If padding is disabled, the final length should be `bytes` data length multiplied by 4/3 rounded up as + // opposed to when padding is required to fill the last chunk. + // - `4 * data.length` -> 4 characters for each chunk + // - ` + 2` -> Prepare for division rounding up + // - `/ 3` -> Number of 3-bytes chunks (rounded up) + // This is equivalent to: Math.ceil((4 * data.length) / 3) + uint256 resultLength = withPadding ? 4 * ((data.length + 2) / 3) : (4 * data.length + 2) / 3; + + string memory result = new string(resultLength); + + assembly ("memory-safe") { + // Prepare the lookup table (skip the first "length" byte) + let tablePtr := add(table, 1) + + // Prepare result pointer, jump over length + let resultPtr := add(result, 0x20) + let dataPtr := data + let endPtr := add(data, mload(data)) + + // In some cases, the last iteration will read bytes after the end of the data. We cache the value, and + // set it to zero to make sure no dirty bytes are read in that section. + let afterPtr := add(endPtr, 0x20) + let afterCache := mload(afterPtr) + mstore(afterPtr, 0x00) + + // Run over the input, 3 bytes at a time + for {} lt(dataPtr, endPtr) {} { + // Advance 3 bytes + dataPtr := add(dataPtr, 3) + let input := mload(dataPtr) + + // To write each character, shift the 3 byte (24 bits) chunk + // 4 times in blocks of 6 bits for each character (18, 12, 6, 0) + // and apply logical AND with 0x3F to bitmask the least significant 6 bits. + // Use this as an index into the lookup table, mload an entire word + // so the desired character is in the least significant byte, and + // mstore8 this least significant byte into the result and continue. + + mstore8(resultPtr, mload(add(tablePtr, and(shr(18, input), 0x3F)))) + resultPtr := add(resultPtr, 1) // Advance + + mstore8(resultPtr, mload(add(tablePtr, and(shr(12, input), 0x3F)))) + resultPtr := add(resultPtr, 1) // Advance + + mstore8(resultPtr, mload(add(tablePtr, and(shr(6, input), 0x3F)))) + resultPtr := add(resultPtr, 1) // Advance + + mstore8(resultPtr, mload(add(tablePtr, and(input, 0x3F)))) + resultPtr := add(resultPtr, 1) // Advance + } + + // Reset the value that was cached + mstore(afterPtr, afterCache) + + if withPadding { + // When data `bytes` is not exactly 3 bytes long + // it is padded with `=` characters at the end + switch mod(mload(data), 3) + case 1 { + mstore8(sub(resultPtr, 1), 0x3d) + mstore8(sub(resultPtr, 2), 0x3d) + } + case 2 { + mstore8(sub(resultPtr, 1), 0x3d) + } + } + } + + return result; + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/utils/Blockhash.sol b/dependencies/@openzeppelin-contracts-5.4.0/utils/Blockhash.sol new file mode 100644 index 00000000..d420b8e6 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/utils/Blockhash.sol @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (utils/Blockhash.sol) +pragma solidity ^0.8.20; + +/** + * @dev Library for accessing historical block hashes beyond the standard 256 block limit. + * Uses EIP-2935's history storage contract which maintains a ring buffer of the last + * 8191 block hashes in state. + * + * For blocks within the last 256 blocks, it uses the native `BLOCKHASH` opcode. + * For blocks between 257 and 8191 blocks ago, it queries the EIP-2935 history storage. + * For blocks older than 8191 or future blocks, it returns zero, matching the `BLOCKHASH` behavior. + * + * NOTE: After EIP-2935 activation, it takes 8191 blocks to completely fill the history. + * Before that, only block hashes since the fork block will be available. + */ +library Blockhash { + /// @dev Address of the EIP-2935 history storage contract. + address internal constant HISTORY_STORAGE_ADDRESS = 0x0000F90827F1C53a10cb7A02335B175320002935; + + /** + * @dev Retrieves the block hash for any historical block within the supported range. + * + * NOTE: The function gracefully handles future blocks and blocks beyond the history window + * by returning zero, consistent with the EVM's native `BLOCKHASH` behavior. + */ + function blockHash(uint256 blockNumber) internal view returns (bytes32) { + uint256 current = block.number; + uint256 distance; + + unchecked { + // Can only wrap around to `current + 1` given `block.number - (2**256 - 1) = block.number + 1` + distance = current - blockNumber; + } + + return distance < 257 ? blockhash(blockNumber) : _historyStorageCall(blockNumber); + } + + /// @dev Internal function to query the EIP-2935 history storage contract. + function _historyStorageCall(uint256 blockNumber) private view returns (bytes32 hash) { + assembly ("memory-safe") { + // Store the blockNumber in scratch space + mstore(0x00, blockNumber) + mstore(0x20, 0) + + // call history storage address + pop(staticcall(gas(), HISTORY_STORAGE_ADDRESS, 0x00, 0x20, 0x20, 0x20)) + + // load result + hash := mload(0x20) + } + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/utils/Bytes.sol b/dependencies/@openzeppelin-contracts-5.4.0/utils/Bytes.sol new file mode 100644 index 00000000..15084ec3 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/utils/Bytes.sol @@ -0,0 +1,113 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (utils/Bytes.sol) + +pragma solidity ^0.8.24; + +import {Math} from "./math/Math.sol"; + +/** + * @dev Bytes operations. + */ +library Bytes { + /** + * @dev Forward search for `s` in `buffer` + * * If `s` is present in the buffer, returns the index of the first instance + * * If `s` is not present in the buffer, returns type(uint256).max + * + * NOTE: replicates the behavior of https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf[Javascript's `Array.indexOf`] + */ + function indexOf(bytes memory buffer, bytes1 s) internal pure returns (uint256) { + return indexOf(buffer, s, 0); + } + + /** + * @dev Forward search for `s` in `buffer` starting at position `pos` + * * If `s` is present in the buffer (at or after `pos`), returns the index of the next instance + * * If `s` is not present in the buffer (at or after `pos`), returns type(uint256).max + * + * NOTE: replicates the behavior of https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf[Javascript's `Array.indexOf`] + */ + function indexOf(bytes memory buffer, bytes1 s, uint256 pos) internal pure returns (uint256) { + uint256 length = buffer.length; + for (uint256 i = pos; i < length; ++i) { + if (bytes1(_unsafeReadBytesOffset(buffer, i)) == s) { + return i; + } + } + return type(uint256).max; + } + + /** + * @dev Backward search for `s` in `buffer` + * * If `s` is present in the buffer, returns the index of the last instance + * * If `s` is not present in the buffer, returns type(uint256).max + * + * NOTE: replicates the behavior of https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/lastIndexOf[Javascript's `Array.lastIndexOf`] + */ + function lastIndexOf(bytes memory buffer, bytes1 s) internal pure returns (uint256) { + return lastIndexOf(buffer, s, type(uint256).max); + } + + /** + * @dev Backward search for `s` in `buffer` starting at position `pos` + * * If `s` is present in the buffer (at or before `pos`), returns the index of the previous instance + * * If `s` is not present in the buffer (at or before `pos`), returns type(uint256).max + * + * NOTE: replicates the behavior of https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/lastIndexOf[Javascript's `Array.lastIndexOf`] + */ + function lastIndexOf(bytes memory buffer, bytes1 s, uint256 pos) internal pure returns (uint256) { + unchecked { + uint256 length = buffer.length; + for (uint256 i = Math.min(Math.saturatingAdd(pos, 1), length); i > 0; --i) { + if (bytes1(_unsafeReadBytesOffset(buffer, i - 1)) == s) { + return i - 1; + } + } + return type(uint256).max; + } + } + + /** + * @dev Copies the content of `buffer`, from `start` (included) to the end of `buffer` into a new bytes object in + * memory. + * + * NOTE: replicates the behavior of https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice[Javascript's `Array.slice`] + */ + function slice(bytes memory buffer, uint256 start) internal pure returns (bytes memory) { + return slice(buffer, start, buffer.length); + } + + /** + * @dev Copies the content of `buffer`, from `start` (included) to `end` (excluded) into a new bytes object in + * memory. + * + * NOTE: replicates the behavior of https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice[Javascript's `Array.slice`] + */ + function slice(bytes memory buffer, uint256 start, uint256 end) internal pure returns (bytes memory) { + // sanitize + uint256 length = buffer.length; + end = Math.min(end, length); + start = Math.min(start, end); + + // allocate and copy + bytes memory result = new bytes(end - start); + assembly ("memory-safe") { + mcopy(add(result, 0x20), add(add(buffer, 0x20), start), sub(end, start)) + } + + return result; + } + + /** + * @dev Reads a bytes32 from a bytes array without bounds checking. + * + * NOTE: making this function internal would mean it could be used with memory unsafe offset, and marking the + * assembly block as such would prevent some optimizations. + */ + function _unsafeReadBytesOffset(bytes memory buffer, uint256 offset) private pure returns (bytes32 value) { + // This is not memory safe in the general case, but all calls to this private function are within bounds. + assembly ("memory-safe") { + value := mload(add(add(buffer, 0x20), offset)) + } + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/utils/CAIP10.sol b/dependencies/@openzeppelin-contracts-5.4.0/utils/CAIP10.sol new file mode 100644 index 00000000..84b35da0 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/utils/CAIP10.sol @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.2.0) (utils/CAIP10.sol) + +pragma solidity ^0.8.24; + +import {Bytes} from "./Bytes.sol"; +import {Strings} from "./Strings.sol"; +import {CAIP2} from "./CAIP2.sol"; + +/** + * @dev Helper library to format and parse CAIP-10 identifiers + * + * https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-10.md[CAIP-10] defines account identifiers as: + * account_id: chain_id + ":" + account_address + * chain_id: [-a-z0-9]{3,8}:[-_a-zA-Z0-9]{1,32} (See {CAIP2}) + * account_address: [-.%a-zA-Z0-9]{1,128} + * + * WARNING: According to [CAIP-10's canonicalization section](https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-10.md#canonicalization), + * the implementation remains at the developer's discretion. Please note that case variations may introduce ambiguity. + * For example, when building hashes to identify accounts or data associated to them, multiple representations of the + * same account would derive to different hashes. For EVM chains, we recommend using checksummed addresses for the + * "account_address" part. They can be generated onchain using {Strings-toChecksumHexString}. + */ +library CAIP10 { + using Strings for address; + using Bytes for bytes; + + /// @dev Return the CAIP-10 identifier for an account on the current (local) chain. + function local(address account) internal view returns (string memory) { + return format(CAIP2.local(), account.toChecksumHexString()); + } + + /** + * @dev Return the CAIP-10 identifier for a given caip2 chain and account. + * + * NOTE: This function does not verify that the inputs are properly formatted. + */ + function format(string memory caip2, string memory account) internal pure returns (string memory) { + return string.concat(caip2, ":", account); + } + + /** + * @dev Parse a CAIP-10 identifier into its components. + * + * NOTE: This function does not verify that the CAIP-10 input is properly formatted. The `caip2` return can be + * parsed using the {CAIP2} library. + */ + function parse(string memory caip10) internal pure returns (string memory caip2, string memory account) { + bytes memory buffer = bytes(caip10); + + uint256 pos = buffer.lastIndexOf(":"); + return (string(buffer.slice(0, pos)), string(buffer.slice(pos + 1))); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/utils/CAIP2.sol b/dependencies/@openzeppelin-contracts-5.4.0/utils/CAIP2.sol new file mode 100644 index 00000000..d06dd6da --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/utils/CAIP2.sol @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.2.0) (utils/CAIP2.sol) + +pragma solidity ^0.8.24; + +import {Bytes} from "./Bytes.sol"; +import {Strings} from "./Strings.sol"; + +/** + * @dev Helper library to format and parse CAIP-2 identifiers + * + * https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-2.md[CAIP-2] defines chain identifiers as: + * chain_id: namespace + ":" + reference + * namespace: [-a-z0-9]{3,8} + * reference: [-_a-zA-Z0-9]{1,32} + * + * WARNING: In some cases, multiple CAIP-2 identifiers may all be valid representation of a single chain. + * For EVM chains, it is recommended to use `eip155:xxx` as the canonical representation (where `xxx` is + * the EIP-155 chain id). Consider the possible ambiguity when processing CAIP-2 identifiers or when using them + * in the context of hashes. + */ +library CAIP2 { + using Strings for uint256; + using Bytes for bytes; + + /// @dev Return the CAIP-2 identifier for the current (local) chain. + function local() internal view returns (string memory) { + return format("eip155", block.chainid.toString()); + } + + /** + * @dev Return the CAIP-2 identifier for a given namespace and reference. + * + * NOTE: This function does not verify that the inputs are properly formatted. + */ + function format(string memory namespace, string memory ref) internal pure returns (string memory) { + return string.concat(namespace, ":", ref); + } + + /** + * @dev Parse a CAIP-2 identifier into its components. + * + * NOTE: This function does not verify that the CAIP-2 input is properly formatted. + */ + function parse(string memory caip2) internal pure returns (string memory namespace, string memory ref) { + bytes memory buffer = bytes(caip2); + + uint256 pos = buffer.indexOf(":"); + return (string(buffer.slice(0, pos)), string(buffer.slice(pos + 1))); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/utils/Calldata.sol b/dependencies/@openzeppelin-contracts-5.4.0/utils/Calldata.sol new file mode 100644 index 00000000..41860b29 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/utils/Calldata.sol @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.3.0) (utils/Calldata.sol) + +pragma solidity ^0.8.20; + +/** + * @dev Helper library for manipulating objects in calldata. + */ +library Calldata { + // slither-disable-next-line write-after-write + function emptyBytes() internal pure returns (bytes calldata result) { + assembly ("memory-safe") { + result.offset := 0 + result.length := 0 + } + } + + // slither-disable-next-line write-after-write + function emptyString() internal pure returns (string calldata result) { + assembly ("memory-safe") { + result.offset := 0 + result.length := 0 + } + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/utils/Comparators.sol b/dependencies/@openzeppelin-contracts-5.4.0/utils/Comparators.sol new file mode 100644 index 00000000..a8c5e73d --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/utils/Comparators.sol @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.1.0) (utils/Comparators.sol) + +pragma solidity ^0.8.20; + +/** + * @dev Provides a set of functions to compare values. + * + * _Available since v5.1._ + */ +library Comparators { + function lt(uint256 a, uint256 b) internal pure returns (bool) { + return a < b; + } + + function gt(uint256 a, uint256 b) internal pure returns (bool) { + return a > b; + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/utils/Context.sol b/dependencies/@openzeppelin-contracts-5.4.0/utils/Context.sol new file mode 100644 index 00000000..4e535fe0 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/utils/Context.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) + +pragma solidity ^0.8.20; + +/** + * @dev Provides information about the current execution context, including the + * sender of the transaction and its data. While these are generally available + * via msg.sender and msg.data, they should not be accessed in such a direct + * manner, since when dealing with meta-transactions the account sending and + * paying for execution may not be the actual sender (as far as an application + * is concerned). + * + * This contract is only required for intermediate, library-like contracts. + */ +abstract contract Context { + function _msgSender() internal view virtual returns (address) { + return msg.sender; + } + + function _msgData() internal view virtual returns (bytes calldata) { + return msg.data; + } + + function _contextSuffixLength() internal view virtual returns (uint256) { + return 0; + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/utils/Create2.sol b/dependencies/@openzeppelin-contracts-5.4.0/utils/Create2.sol new file mode 100644 index 00000000..ffd39d9a --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/utils/Create2.sol @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.1.0) (utils/Create2.sol) + +pragma solidity ^0.8.20; + +import {Errors} from "./Errors.sol"; + +/** + * @dev Helper to make usage of the `CREATE2` EVM opcode easier and safer. + * `CREATE2` can be used to compute in advance the address where a smart + * contract will be deployed, which allows for interesting new mechanisms known + * as 'counterfactual interactions'. + * + * See the https://eips.ethereum.org/EIPS/eip-1014#motivation[EIP] for more + * information. + */ +library Create2 { + /** + * @dev There's no code to deploy. + */ + error Create2EmptyBytecode(); + + /** + * @dev Deploys a contract using `CREATE2`. The address where the contract + * will be deployed can be known in advance via {computeAddress}. + * + * The bytecode for a contract can be obtained from Solidity with + * `type(contractName).creationCode`. + * + * Requirements: + * + * - `bytecode` must not be empty. + * - `salt` must have not been used for `bytecode` already. + * - the factory must have a balance of at least `amount`. + * - if `amount` is non-zero, `bytecode` must have a `payable` constructor. + */ + function deploy(uint256 amount, bytes32 salt, bytes memory bytecode) internal returns (address addr) { + if (address(this).balance < amount) { + revert Errors.InsufficientBalance(address(this).balance, amount); + } + if (bytecode.length == 0) { + revert Create2EmptyBytecode(); + } + assembly ("memory-safe") { + addr := create2(amount, add(bytecode, 0x20), mload(bytecode), salt) + // if no address was created, and returndata is not empty, bubble revert + if and(iszero(addr), not(iszero(returndatasize()))) { + let p := mload(0x40) + returndatacopy(p, 0, returndatasize()) + revert(p, returndatasize()) + } + } + if (addr == address(0)) { + revert Errors.FailedDeployment(); + } + } + + /** + * @dev Returns the address where a contract will be stored if deployed via {deploy}. Any change in the + * `bytecodeHash` or `salt` will result in a new destination address. + */ + function computeAddress(bytes32 salt, bytes32 bytecodeHash) internal view returns (address) { + return computeAddress(salt, bytecodeHash, address(this)); + } + + /** + * @dev Returns the address where a contract will be stored if deployed via {deploy} from a contract located at + * `deployer`. If `deployer` is this contract's address, returns the same value as {computeAddress}. + */ + function computeAddress(bytes32 salt, bytes32 bytecodeHash, address deployer) internal pure returns (address addr) { + assembly ("memory-safe") { + let ptr := mload(0x40) // Get free memory pointer + + // | | ↓ ptr ... ↓ ptr + 0x0B (start) ... ↓ ptr + 0x20 ... ↓ ptr + 0x40 ... | + // |-------------------|---------------------------------------------------------------------------| + // | bytecodeHash | CCCCCCCCCCCCC...CC | + // | salt | BBBBBBBBBBBBB...BB | + // | deployer | 000000...0000AAAAAAAAAAAAAAAAAAA...AA | + // | 0xFF | FF | + // |-------------------|---------------------------------------------------------------------------| + // | memory | 000000...00FFAAAAAAAAAAAAAAAAAAA...AABBBBBBBBBBBBB...BBCCCCCCCCCCCCC...CC | + // | keccak(start, 85) | ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ | + + mstore(add(ptr, 0x40), bytecodeHash) + mstore(add(ptr, 0x20), salt) + mstore(ptr, deployer) // Right-aligned with 12 preceding garbage bytes + let start := add(ptr, 0x0b) // The hashed data starts at the final garbage byte which we will set to 0xff + mstore8(start, 0xff) + addr := and(keccak256(start, 85), 0xffffffffffffffffffffffffffffffffffffffff) + } + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/utils/Errors.sol b/dependencies/@openzeppelin-contracts-5.4.0/utils/Errors.sol new file mode 100644 index 00000000..442fc189 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/utils/Errors.sol @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.1.0) (utils/Errors.sol) + +pragma solidity ^0.8.20; + +/** + * @dev Collection of common custom errors used in multiple contracts + * + * IMPORTANT: Backwards compatibility is not guaranteed in future versions of the library. + * It is recommended to avoid relying on the error API for critical functionality. + * + * _Available since v5.1._ + */ +library Errors { + /** + * @dev The ETH balance of the account is not enough to perform the operation. + */ + error InsufficientBalance(uint256 balance, uint256 needed); + + /** + * @dev A call to an address target failed. The target may have reverted. + */ + error FailedCall(); + + /** + * @dev The deployment failed. + */ + error FailedDeployment(); + + /** + * @dev A necessary precompile is missing. + */ + error MissingPrecompile(address); +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/utils/Multicall.sol b/dependencies/@openzeppelin-contracts-5.4.0/utils/Multicall.sol new file mode 100644 index 00000000..94222feb --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/utils/Multicall.sol @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.3.0) (utils/Multicall.sol) + +pragma solidity ^0.8.20; + +import {Address} from "./Address.sol"; +import {Context} from "./Context.sol"; + +/** + * @dev Provides a function to batch together multiple calls in a single external call. + * + * Consider any assumption about calldata validation performed by the sender may be violated if it's not especially + * careful about sending transactions invoking {multicall}. For example, a relay address that filters function + * selectors won't filter calls nested within a {multicall} operation. + * + * NOTE: Since 5.0.1 and 4.9.4, this contract identifies non-canonical contexts (i.e. `msg.sender` is not {Context-_msgSender}). + * If a non-canonical context is identified, the following self `delegatecall` appends the last bytes of `msg.data` + * to the subcall. This makes it safe to use with {ERC2771Context}. Contexts that don't affect the resolution of + * {Context-_msgSender} are not propagated to subcalls. + */ +abstract contract Multicall is Context { + /** + * @dev Receives and executes a batch of function calls on this contract. + * @custom:oz-upgrades-unsafe-allow-reachable delegatecall + */ + function multicall(bytes[] calldata data) external virtual returns (bytes[] memory results) { + bytes memory context = msg.sender == _msgSender() + ? new bytes(0) + : msg.data[msg.data.length - _contextSuffixLength():]; + + results = new bytes[](data.length); + for (uint256 i = 0; i < data.length; i++) { + results[i] = Address.functionDelegateCall(address(this), bytes.concat(data[i], context)); + } + return results; + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/utils/Nonces.sol b/dependencies/@openzeppelin-contracts-5.4.0/utils/Nonces.sol new file mode 100644 index 00000000..37451ff9 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/utils/Nonces.sol @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.0.0) (utils/Nonces.sol) +pragma solidity ^0.8.20; + +/** + * @dev Provides tracking nonces for addresses. Nonces will only increment. + */ +abstract contract Nonces { + /** + * @dev The nonce used for an `account` is not the expected current nonce. + */ + error InvalidAccountNonce(address account, uint256 currentNonce); + + mapping(address account => uint256) private _nonces; + + /** + * @dev Returns the next unused nonce for an address. + */ + function nonces(address owner) public view virtual returns (uint256) { + return _nonces[owner]; + } + + /** + * @dev Consumes a nonce. + * + * Returns the current value and increments nonce. + */ + function _useNonce(address owner) internal virtual returns (uint256) { + // For each account, the nonce has an initial value of 0, can only be incremented by one, and cannot be + // decremented or reset. This guarantees that the nonce never overflows. + unchecked { + // It is important to do x++ and not ++x here. + return _nonces[owner]++; + } + } + + /** + * @dev Same as {_useNonce} but checking that `nonce` is the next valid for `owner`. + */ + function _useCheckedNonce(address owner, uint256 nonce) internal virtual { + uint256 current = _useNonce(owner); + if (nonce != current) { + revert InvalidAccountNonce(owner, current); + } + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/utils/NoncesKeyed.sol b/dependencies/@openzeppelin-contracts-5.4.0/utils/NoncesKeyed.sol new file mode 100644 index 00000000..df9c5704 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/utils/NoncesKeyed.sol @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.2.0) (utils/NoncesKeyed.sol) +pragma solidity ^0.8.20; + +import {Nonces} from "./Nonces.sol"; + +/** + * @dev Alternative to {Nonces}, that supports key-ed nonces. + * + * Follows the https://eips.ethereum.org/EIPS/eip-4337#semi-abstracted-nonce-support[ERC-4337's semi-abstracted nonce system]. + * + * NOTE: This contract inherits from {Nonces} and reuses its storage for the first nonce key (i.e. `0`). This + * makes upgrading from {Nonces} to {NoncesKeyed} safe when using their upgradeable versions (e.g. `NoncesKeyedUpgradeable`). + * Doing so will NOT reset the current state of nonces, avoiding replay attacks where a nonce is reused after the upgrade. + */ +abstract contract NoncesKeyed is Nonces { + mapping(address owner => mapping(uint192 key => uint64)) private _nonces; + + /// @dev Returns the next unused nonce for an address and key. Result contains the key prefix. + function nonces(address owner, uint192 key) public view virtual returns (uint256) { + return key == 0 ? nonces(owner) : _pack(key, _nonces[owner][key]); + } + + /** + * @dev Consumes the next unused nonce for an address and key. + * + * Returns the current value without the key prefix. Consumed nonce is increased, so calling this function twice + * with the same arguments will return different (sequential) results. + */ + function _useNonce(address owner, uint192 key) internal virtual returns (uint256) { + // For each account, the nonce has an initial value of 0, can only be incremented by one, and cannot be + // decremented or reset. This guarantees that the nonce never overflows. + unchecked { + // It is important to do x++ and not ++x here. + return key == 0 ? _useNonce(owner) : _pack(key, _nonces[owner][key]++); + } + } + + /** + * @dev Same as {_useNonce} but checking that `nonce` is the next valid for `owner`. + * + * This version takes the key and the nonce in a single uint256 parameter: + * - use the first 24 bytes for the key + * - use the last 8 bytes for the nonce + */ + function _useCheckedNonce(address owner, uint256 keyNonce) internal virtual override { + (uint192 key, ) = _unpack(keyNonce); + if (key == 0) { + super._useCheckedNonce(owner, keyNonce); + } else { + uint256 current = _useNonce(owner, key); + if (keyNonce != current) revert InvalidAccountNonce(owner, current); + } + } + + /** + * @dev Same as {_useNonce} but checking that `nonce` is the next valid for `owner`. + * + * This version takes the key and the nonce as two different parameters. + */ + function _useCheckedNonce(address owner, uint192 key, uint64 nonce) internal virtual { + _useCheckedNonce(owner, _pack(key, nonce)); + } + + /// @dev Pack key and nonce into a keyNonce + function _pack(uint192 key, uint64 nonce) private pure returns (uint256) { + return (uint256(key) << 64) | nonce; + } + + /// @dev Unpack a keyNonce into its key and nonce components + function _unpack(uint256 keyNonce) private pure returns (uint192 key, uint64 nonce) { + return (uint192(keyNonce >> 64), uint64(keyNonce)); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/utils/Packing.sol b/dependencies/@openzeppelin-contracts-5.4.0/utils/Packing.sol new file mode 100644 index 00000000..f7c5d6fc --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/utils/Packing.sol @@ -0,0 +1,1656 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.2.0) (utils/Packing.sol) +// This file was procedurally generated from scripts/generate/templates/Packing.js. + +pragma solidity ^0.8.20; + +/** + * @dev Helper library packing and unpacking multiple values into bytesXX. + * + * Example usage: + * + * ```solidity + * library MyPacker { + * type MyType is bytes32; + * + * function _pack(address account, bytes4 selector, uint64 period) external pure returns (MyType) { + * bytes12 subpack = Packing.pack_4_8(selector, bytes8(period)); + * bytes32 pack = Packing.pack_20_12(bytes20(account), subpack); + * return MyType.wrap(pack); + * } + * + * function _unpack(MyType self) external pure returns (address, bytes4, uint64) { + * bytes32 pack = MyType.unwrap(self); + * return ( + * address(Packing.extract_32_20(pack, 0)), + * Packing.extract_32_4(pack, 20), + * uint64(Packing.extract_32_8(pack, 24)) + * ); + * } + * } + * ``` + * + * _Available since v5.1._ + */ +// solhint-disable func-name-mixedcase +library Packing { + error OutOfRangeAccess(); + + function pack_1_1(bytes1 left, bytes1 right) internal pure returns (bytes2 result) { + assembly ("memory-safe") { + left := and(left, shl(248, not(0))) + right := and(right, shl(248, not(0))) + result := or(left, shr(8, right)) + } + } + + function pack_2_2(bytes2 left, bytes2 right) internal pure returns (bytes4 result) { + assembly ("memory-safe") { + left := and(left, shl(240, not(0))) + right := and(right, shl(240, not(0))) + result := or(left, shr(16, right)) + } + } + + function pack_2_4(bytes2 left, bytes4 right) internal pure returns (bytes6 result) { + assembly ("memory-safe") { + left := and(left, shl(240, not(0))) + right := and(right, shl(224, not(0))) + result := or(left, shr(16, right)) + } + } + + function pack_2_6(bytes2 left, bytes6 right) internal pure returns (bytes8 result) { + assembly ("memory-safe") { + left := and(left, shl(240, not(0))) + right := and(right, shl(208, not(0))) + result := or(left, shr(16, right)) + } + } + + function pack_2_8(bytes2 left, bytes8 right) internal pure returns (bytes10 result) { + assembly ("memory-safe") { + left := and(left, shl(240, not(0))) + right := and(right, shl(192, not(0))) + result := or(left, shr(16, right)) + } + } + + function pack_2_10(bytes2 left, bytes10 right) internal pure returns (bytes12 result) { + assembly ("memory-safe") { + left := and(left, shl(240, not(0))) + right := and(right, shl(176, not(0))) + result := or(left, shr(16, right)) + } + } + + function pack_2_20(bytes2 left, bytes20 right) internal pure returns (bytes22 result) { + assembly ("memory-safe") { + left := and(left, shl(240, not(0))) + right := and(right, shl(96, not(0))) + result := or(left, shr(16, right)) + } + } + + function pack_2_22(bytes2 left, bytes22 right) internal pure returns (bytes24 result) { + assembly ("memory-safe") { + left := and(left, shl(240, not(0))) + right := and(right, shl(80, not(0))) + result := or(left, shr(16, right)) + } + } + + function pack_4_2(bytes4 left, bytes2 right) internal pure returns (bytes6 result) { + assembly ("memory-safe") { + left := and(left, shl(224, not(0))) + right := and(right, shl(240, not(0))) + result := or(left, shr(32, right)) + } + } + + function pack_4_4(bytes4 left, bytes4 right) internal pure returns (bytes8 result) { + assembly ("memory-safe") { + left := and(left, shl(224, not(0))) + right := and(right, shl(224, not(0))) + result := or(left, shr(32, right)) + } + } + + function pack_4_6(bytes4 left, bytes6 right) internal pure returns (bytes10 result) { + assembly ("memory-safe") { + left := and(left, shl(224, not(0))) + right := and(right, shl(208, not(0))) + result := or(left, shr(32, right)) + } + } + + function pack_4_8(bytes4 left, bytes8 right) internal pure returns (bytes12 result) { + assembly ("memory-safe") { + left := and(left, shl(224, not(0))) + right := and(right, shl(192, not(0))) + result := or(left, shr(32, right)) + } + } + + function pack_4_12(bytes4 left, bytes12 right) internal pure returns (bytes16 result) { + assembly ("memory-safe") { + left := and(left, shl(224, not(0))) + right := and(right, shl(160, not(0))) + result := or(left, shr(32, right)) + } + } + + function pack_4_16(bytes4 left, bytes16 right) internal pure returns (bytes20 result) { + assembly ("memory-safe") { + left := and(left, shl(224, not(0))) + right := and(right, shl(128, not(0))) + result := or(left, shr(32, right)) + } + } + + function pack_4_20(bytes4 left, bytes20 right) internal pure returns (bytes24 result) { + assembly ("memory-safe") { + left := and(left, shl(224, not(0))) + right := and(right, shl(96, not(0))) + result := or(left, shr(32, right)) + } + } + + function pack_4_24(bytes4 left, bytes24 right) internal pure returns (bytes28 result) { + assembly ("memory-safe") { + left := and(left, shl(224, not(0))) + right := and(right, shl(64, not(0))) + result := or(left, shr(32, right)) + } + } + + function pack_4_28(bytes4 left, bytes28 right) internal pure returns (bytes32 result) { + assembly ("memory-safe") { + left := and(left, shl(224, not(0))) + right := and(right, shl(32, not(0))) + result := or(left, shr(32, right)) + } + } + + function pack_6_2(bytes6 left, bytes2 right) internal pure returns (bytes8 result) { + assembly ("memory-safe") { + left := and(left, shl(208, not(0))) + right := and(right, shl(240, not(0))) + result := or(left, shr(48, right)) + } + } + + function pack_6_4(bytes6 left, bytes4 right) internal pure returns (bytes10 result) { + assembly ("memory-safe") { + left := and(left, shl(208, not(0))) + right := and(right, shl(224, not(0))) + result := or(left, shr(48, right)) + } + } + + function pack_6_6(bytes6 left, bytes6 right) internal pure returns (bytes12 result) { + assembly ("memory-safe") { + left := and(left, shl(208, not(0))) + right := and(right, shl(208, not(0))) + result := or(left, shr(48, right)) + } + } + + function pack_6_10(bytes6 left, bytes10 right) internal pure returns (bytes16 result) { + assembly ("memory-safe") { + left := and(left, shl(208, not(0))) + right := and(right, shl(176, not(0))) + result := or(left, shr(48, right)) + } + } + + function pack_6_16(bytes6 left, bytes16 right) internal pure returns (bytes22 result) { + assembly ("memory-safe") { + left := and(left, shl(208, not(0))) + right := and(right, shl(128, not(0))) + result := or(left, shr(48, right)) + } + } + + function pack_6_22(bytes6 left, bytes22 right) internal pure returns (bytes28 result) { + assembly ("memory-safe") { + left := and(left, shl(208, not(0))) + right := and(right, shl(80, not(0))) + result := or(left, shr(48, right)) + } + } + + function pack_8_2(bytes8 left, bytes2 right) internal pure returns (bytes10 result) { + assembly ("memory-safe") { + left := and(left, shl(192, not(0))) + right := and(right, shl(240, not(0))) + result := or(left, shr(64, right)) + } + } + + function pack_8_4(bytes8 left, bytes4 right) internal pure returns (bytes12 result) { + assembly ("memory-safe") { + left := and(left, shl(192, not(0))) + right := and(right, shl(224, not(0))) + result := or(left, shr(64, right)) + } + } + + function pack_8_8(bytes8 left, bytes8 right) internal pure returns (bytes16 result) { + assembly ("memory-safe") { + left := and(left, shl(192, not(0))) + right := and(right, shl(192, not(0))) + result := or(left, shr(64, right)) + } + } + + function pack_8_12(bytes8 left, bytes12 right) internal pure returns (bytes20 result) { + assembly ("memory-safe") { + left := and(left, shl(192, not(0))) + right := and(right, shl(160, not(0))) + result := or(left, shr(64, right)) + } + } + + function pack_8_16(bytes8 left, bytes16 right) internal pure returns (bytes24 result) { + assembly ("memory-safe") { + left := and(left, shl(192, not(0))) + right := and(right, shl(128, not(0))) + result := or(left, shr(64, right)) + } + } + + function pack_8_20(bytes8 left, bytes20 right) internal pure returns (bytes28 result) { + assembly ("memory-safe") { + left := and(left, shl(192, not(0))) + right := and(right, shl(96, not(0))) + result := or(left, shr(64, right)) + } + } + + function pack_8_24(bytes8 left, bytes24 right) internal pure returns (bytes32 result) { + assembly ("memory-safe") { + left := and(left, shl(192, not(0))) + right := and(right, shl(64, not(0))) + result := or(left, shr(64, right)) + } + } + + function pack_10_2(bytes10 left, bytes2 right) internal pure returns (bytes12 result) { + assembly ("memory-safe") { + left := and(left, shl(176, not(0))) + right := and(right, shl(240, not(0))) + result := or(left, shr(80, right)) + } + } + + function pack_10_6(bytes10 left, bytes6 right) internal pure returns (bytes16 result) { + assembly ("memory-safe") { + left := and(left, shl(176, not(0))) + right := and(right, shl(208, not(0))) + result := or(left, shr(80, right)) + } + } + + function pack_10_10(bytes10 left, bytes10 right) internal pure returns (bytes20 result) { + assembly ("memory-safe") { + left := and(left, shl(176, not(0))) + right := and(right, shl(176, not(0))) + result := or(left, shr(80, right)) + } + } + + function pack_10_12(bytes10 left, bytes12 right) internal pure returns (bytes22 result) { + assembly ("memory-safe") { + left := and(left, shl(176, not(0))) + right := and(right, shl(160, not(0))) + result := or(left, shr(80, right)) + } + } + + function pack_10_22(bytes10 left, bytes22 right) internal pure returns (bytes32 result) { + assembly ("memory-safe") { + left := and(left, shl(176, not(0))) + right := and(right, shl(80, not(0))) + result := or(left, shr(80, right)) + } + } + + function pack_12_4(bytes12 left, bytes4 right) internal pure returns (bytes16 result) { + assembly ("memory-safe") { + left := and(left, shl(160, not(0))) + right := and(right, shl(224, not(0))) + result := or(left, shr(96, right)) + } + } + + function pack_12_8(bytes12 left, bytes8 right) internal pure returns (bytes20 result) { + assembly ("memory-safe") { + left := and(left, shl(160, not(0))) + right := and(right, shl(192, not(0))) + result := or(left, shr(96, right)) + } + } + + function pack_12_10(bytes12 left, bytes10 right) internal pure returns (bytes22 result) { + assembly ("memory-safe") { + left := and(left, shl(160, not(0))) + right := and(right, shl(176, not(0))) + result := or(left, shr(96, right)) + } + } + + function pack_12_12(bytes12 left, bytes12 right) internal pure returns (bytes24 result) { + assembly ("memory-safe") { + left := and(left, shl(160, not(0))) + right := and(right, shl(160, not(0))) + result := or(left, shr(96, right)) + } + } + + function pack_12_16(bytes12 left, bytes16 right) internal pure returns (bytes28 result) { + assembly ("memory-safe") { + left := and(left, shl(160, not(0))) + right := and(right, shl(128, not(0))) + result := or(left, shr(96, right)) + } + } + + function pack_12_20(bytes12 left, bytes20 right) internal pure returns (bytes32 result) { + assembly ("memory-safe") { + left := and(left, shl(160, not(0))) + right := and(right, shl(96, not(0))) + result := or(left, shr(96, right)) + } + } + + function pack_16_4(bytes16 left, bytes4 right) internal pure returns (bytes20 result) { + assembly ("memory-safe") { + left := and(left, shl(128, not(0))) + right := and(right, shl(224, not(0))) + result := or(left, shr(128, right)) + } + } + + function pack_16_6(bytes16 left, bytes6 right) internal pure returns (bytes22 result) { + assembly ("memory-safe") { + left := and(left, shl(128, not(0))) + right := and(right, shl(208, not(0))) + result := or(left, shr(128, right)) + } + } + + function pack_16_8(bytes16 left, bytes8 right) internal pure returns (bytes24 result) { + assembly ("memory-safe") { + left := and(left, shl(128, not(0))) + right := and(right, shl(192, not(0))) + result := or(left, shr(128, right)) + } + } + + function pack_16_12(bytes16 left, bytes12 right) internal pure returns (bytes28 result) { + assembly ("memory-safe") { + left := and(left, shl(128, not(0))) + right := and(right, shl(160, not(0))) + result := or(left, shr(128, right)) + } + } + + function pack_16_16(bytes16 left, bytes16 right) internal pure returns (bytes32 result) { + assembly ("memory-safe") { + left := and(left, shl(128, not(0))) + right := and(right, shl(128, not(0))) + result := or(left, shr(128, right)) + } + } + + function pack_20_2(bytes20 left, bytes2 right) internal pure returns (bytes22 result) { + assembly ("memory-safe") { + left := and(left, shl(96, not(0))) + right := and(right, shl(240, not(0))) + result := or(left, shr(160, right)) + } + } + + function pack_20_4(bytes20 left, bytes4 right) internal pure returns (bytes24 result) { + assembly ("memory-safe") { + left := and(left, shl(96, not(0))) + right := and(right, shl(224, not(0))) + result := or(left, shr(160, right)) + } + } + + function pack_20_8(bytes20 left, bytes8 right) internal pure returns (bytes28 result) { + assembly ("memory-safe") { + left := and(left, shl(96, not(0))) + right := and(right, shl(192, not(0))) + result := or(left, shr(160, right)) + } + } + + function pack_20_12(bytes20 left, bytes12 right) internal pure returns (bytes32 result) { + assembly ("memory-safe") { + left := and(left, shl(96, not(0))) + right := and(right, shl(160, not(0))) + result := or(left, shr(160, right)) + } + } + + function pack_22_2(bytes22 left, bytes2 right) internal pure returns (bytes24 result) { + assembly ("memory-safe") { + left := and(left, shl(80, not(0))) + right := and(right, shl(240, not(0))) + result := or(left, shr(176, right)) + } + } + + function pack_22_6(bytes22 left, bytes6 right) internal pure returns (bytes28 result) { + assembly ("memory-safe") { + left := and(left, shl(80, not(0))) + right := and(right, shl(208, not(0))) + result := or(left, shr(176, right)) + } + } + + function pack_22_10(bytes22 left, bytes10 right) internal pure returns (bytes32 result) { + assembly ("memory-safe") { + left := and(left, shl(80, not(0))) + right := and(right, shl(176, not(0))) + result := or(left, shr(176, right)) + } + } + + function pack_24_4(bytes24 left, bytes4 right) internal pure returns (bytes28 result) { + assembly ("memory-safe") { + left := and(left, shl(64, not(0))) + right := and(right, shl(224, not(0))) + result := or(left, shr(192, right)) + } + } + + function pack_24_8(bytes24 left, bytes8 right) internal pure returns (bytes32 result) { + assembly ("memory-safe") { + left := and(left, shl(64, not(0))) + right := and(right, shl(192, not(0))) + result := or(left, shr(192, right)) + } + } + + function pack_28_4(bytes28 left, bytes4 right) internal pure returns (bytes32 result) { + assembly ("memory-safe") { + left := and(left, shl(32, not(0))) + right := and(right, shl(224, not(0))) + result := or(left, shr(224, right)) + } + } + + function extract_2_1(bytes2 self, uint8 offset) internal pure returns (bytes1 result) { + if (offset > 1) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(248, not(0))) + } + } + + function replace_2_1(bytes2 self, bytes1 value, uint8 offset) internal pure returns (bytes2 result) { + bytes1 oldValue = extract_2_1(self, offset); + assembly ("memory-safe") { + value := and(value, shl(248, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_4_1(bytes4 self, uint8 offset) internal pure returns (bytes1 result) { + if (offset > 3) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(248, not(0))) + } + } + + function replace_4_1(bytes4 self, bytes1 value, uint8 offset) internal pure returns (bytes4 result) { + bytes1 oldValue = extract_4_1(self, offset); + assembly ("memory-safe") { + value := and(value, shl(248, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_4_2(bytes4 self, uint8 offset) internal pure returns (bytes2 result) { + if (offset > 2) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(240, not(0))) + } + } + + function replace_4_2(bytes4 self, bytes2 value, uint8 offset) internal pure returns (bytes4 result) { + bytes2 oldValue = extract_4_2(self, offset); + assembly ("memory-safe") { + value := and(value, shl(240, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_6_1(bytes6 self, uint8 offset) internal pure returns (bytes1 result) { + if (offset > 5) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(248, not(0))) + } + } + + function replace_6_1(bytes6 self, bytes1 value, uint8 offset) internal pure returns (bytes6 result) { + bytes1 oldValue = extract_6_1(self, offset); + assembly ("memory-safe") { + value := and(value, shl(248, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_6_2(bytes6 self, uint8 offset) internal pure returns (bytes2 result) { + if (offset > 4) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(240, not(0))) + } + } + + function replace_6_2(bytes6 self, bytes2 value, uint8 offset) internal pure returns (bytes6 result) { + bytes2 oldValue = extract_6_2(self, offset); + assembly ("memory-safe") { + value := and(value, shl(240, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_6_4(bytes6 self, uint8 offset) internal pure returns (bytes4 result) { + if (offset > 2) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(224, not(0))) + } + } + + function replace_6_4(bytes6 self, bytes4 value, uint8 offset) internal pure returns (bytes6 result) { + bytes4 oldValue = extract_6_4(self, offset); + assembly ("memory-safe") { + value := and(value, shl(224, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_8_1(bytes8 self, uint8 offset) internal pure returns (bytes1 result) { + if (offset > 7) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(248, not(0))) + } + } + + function replace_8_1(bytes8 self, bytes1 value, uint8 offset) internal pure returns (bytes8 result) { + bytes1 oldValue = extract_8_1(self, offset); + assembly ("memory-safe") { + value := and(value, shl(248, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_8_2(bytes8 self, uint8 offset) internal pure returns (bytes2 result) { + if (offset > 6) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(240, not(0))) + } + } + + function replace_8_2(bytes8 self, bytes2 value, uint8 offset) internal pure returns (bytes8 result) { + bytes2 oldValue = extract_8_2(self, offset); + assembly ("memory-safe") { + value := and(value, shl(240, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_8_4(bytes8 self, uint8 offset) internal pure returns (bytes4 result) { + if (offset > 4) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(224, not(0))) + } + } + + function replace_8_4(bytes8 self, bytes4 value, uint8 offset) internal pure returns (bytes8 result) { + bytes4 oldValue = extract_8_4(self, offset); + assembly ("memory-safe") { + value := and(value, shl(224, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_8_6(bytes8 self, uint8 offset) internal pure returns (bytes6 result) { + if (offset > 2) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(208, not(0))) + } + } + + function replace_8_6(bytes8 self, bytes6 value, uint8 offset) internal pure returns (bytes8 result) { + bytes6 oldValue = extract_8_6(self, offset); + assembly ("memory-safe") { + value := and(value, shl(208, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_10_1(bytes10 self, uint8 offset) internal pure returns (bytes1 result) { + if (offset > 9) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(248, not(0))) + } + } + + function replace_10_1(bytes10 self, bytes1 value, uint8 offset) internal pure returns (bytes10 result) { + bytes1 oldValue = extract_10_1(self, offset); + assembly ("memory-safe") { + value := and(value, shl(248, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_10_2(bytes10 self, uint8 offset) internal pure returns (bytes2 result) { + if (offset > 8) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(240, not(0))) + } + } + + function replace_10_2(bytes10 self, bytes2 value, uint8 offset) internal pure returns (bytes10 result) { + bytes2 oldValue = extract_10_2(self, offset); + assembly ("memory-safe") { + value := and(value, shl(240, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_10_4(bytes10 self, uint8 offset) internal pure returns (bytes4 result) { + if (offset > 6) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(224, not(0))) + } + } + + function replace_10_4(bytes10 self, bytes4 value, uint8 offset) internal pure returns (bytes10 result) { + bytes4 oldValue = extract_10_4(self, offset); + assembly ("memory-safe") { + value := and(value, shl(224, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_10_6(bytes10 self, uint8 offset) internal pure returns (bytes6 result) { + if (offset > 4) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(208, not(0))) + } + } + + function replace_10_6(bytes10 self, bytes6 value, uint8 offset) internal pure returns (bytes10 result) { + bytes6 oldValue = extract_10_6(self, offset); + assembly ("memory-safe") { + value := and(value, shl(208, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_10_8(bytes10 self, uint8 offset) internal pure returns (bytes8 result) { + if (offset > 2) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(192, not(0))) + } + } + + function replace_10_8(bytes10 self, bytes8 value, uint8 offset) internal pure returns (bytes10 result) { + bytes8 oldValue = extract_10_8(self, offset); + assembly ("memory-safe") { + value := and(value, shl(192, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_12_1(bytes12 self, uint8 offset) internal pure returns (bytes1 result) { + if (offset > 11) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(248, not(0))) + } + } + + function replace_12_1(bytes12 self, bytes1 value, uint8 offset) internal pure returns (bytes12 result) { + bytes1 oldValue = extract_12_1(self, offset); + assembly ("memory-safe") { + value := and(value, shl(248, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_12_2(bytes12 self, uint8 offset) internal pure returns (bytes2 result) { + if (offset > 10) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(240, not(0))) + } + } + + function replace_12_2(bytes12 self, bytes2 value, uint8 offset) internal pure returns (bytes12 result) { + bytes2 oldValue = extract_12_2(self, offset); + assembly ("memory-safe") { + value := and(value, shl(240, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_12_4(bytes12 self, uint8 offset) internal pure returns (bytes4 result) { + if (offset > 8) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(224, not(0))) + } + } + + function replace_12_4(bytes12 self, bytes4 value, uint8 offset) internal pure returns (bytes12 result) { + bytes4 oldValue = extract_12_4(self, offset); + assembly ("memory-safe") { + value := and(value, shl(224, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_12_6(bytes12 self, uint8 offset) internal pure returns (bytes6 result) { + if (offset > 6) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(208, not(0))) + } + } + + function replace_12_6(bytes12 self, bytes6 value, uint8 offset) internal pure returns (bytes12 result) { + bytes6 oldValue = extract_12_6(self, offset); + assembly ("memory-safe") { + value := and(value, shl(208, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_12_8(bytes12 self, uint8 offset) internal pure returns (bytes8 result) { + if (offset > 4) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(192, not(0))) + } + } + + function replace_12_8(bytes12 self, bytes8 value, uint8 offset) internal pure returns (bytes12 result) { + bytes8 oldValue = extract_12_8(self, offset); + assembly ("memory-safe") { + value := and(value, shl(192, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_12_10(bytes12 self, uint8 offset) internal pure returns (bytes10 result) { + if (offset > 2) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(176, not(0))) + } + } + + function replace_12_10(bytes12 self, bytes10 value, uint8 offset) internal pure returns (bytes12 result) { + bytes10 oldValue = extract_12_10(self, offset); + assembly ("memory-safe") { + value := and(value, shl(176, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_16_1(bytes16 self, uint8 offset) internal pure returns (bytes1 result) { + if (offset > 15) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(248, not(0))) + } + } + + function replace_16_1(bytes16 self, bytes1 value, uint8 offset) internal pure returns (bytes16 result) { + bytes1 oldValue = extract_16_1(self, offset); + assembly ("memory-safe") { + value := and(value, shl(248, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_16_2(bytes16 self, uint8 offset) internal pure returns (bytes2 result) { + if (offset > 14) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(240, not(0))) + } + } + + function replace_16_2(bytes16 self, bytes2 value, uint8 offset) internal pure returns (bytes16 result) { + bytes2 oldValue = extract_16_2(self, offset); + assembly ("memory-safe") { + value := and(value, shl(240, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_16_4(bytes16 self, uint8 offset) internal pure returns (bytes4 result) { + if (offset > 12) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(224, not(0))) + } + } + + function replace_16_4(bytes16 self, bytes4 value, uint8 offset) internal pure returns (bytes16 result) { + bytes4 oldValue = extract_16_4(self, offset); + assembly ("memory-safe") { + value := and(value, shl(224, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_16_6(bytes16 self, uint8 offset) internal pure returns (bytes6 result) { + if (offset > 10) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(208, not(0))) + } + } + + function replace_16_6(bytes16 self, bytes6 value, uint8 offset) internal pure returns (bytes16 result) { + bytes6 oldValue = extract_16_6(self, offset); + assembly ("memory-safe") { + value := and(value, shl(208, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_16_8(bytes16 self, uint8 offset) internal pure returns (bytes8 result) { + if (offset > 8) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(192, not(0))) + } + } + + function replace_16_8(bytes16 self, bytes8 value, uint8 offset) internal pure returns (bytes16 result) { + bytes8 oldValue = extract_16_8(self, offset); + assembly ("memory-safe") { + value := and(value, shl(192, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_16_10(bytes16 self, uint8 offset) internal pure returns (bytes10 result) { + if (offset > 6) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(176, not(0))) + } + } + + function replace_16_10(bytes16 self, bytes10 value, uint8 offset) internal pure returns (bytes16 result) { + bytes10 oldValue = extract_16_10(self, offset); + assembly ("memory-safe") { + value := and(value, shl(176, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_16_12(bytes16 self, uint8 offset) internal pure returns (bytes12 result) { + if (offset > 4) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(160, not(0))) + } + } + + function replace_16_12(bytes16 self, bytes12 value, uint8 offset) internal pure returns (bytes16 result) { + bytes12 oldValue = extract_16_12(self, offset); + assembly ("memory-safe") { + value := and(value, shl(160, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_20_1(bytes20 self, uint8 offset) internal pure returns (bytes1 result) { + if (offset > 19) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(248, not(0))) + } + } + + function replace_20_1(bytes20 self, bytes1 value, uint8 offset) internal pure returns (bytes20 result) { + bytes1 oldValue = extract_20_1(self, offset); + assembly ("memory-safe") { + value := and(value, shl(248, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_20_2(bytes20 self, uint8 offset) internal pure returns (bytes2 result) { + if (offset > 18) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(240, not(0))) + } + } + + function replace_20_2(bytes20 self, bytes2 value, uint8 offset) internal pure returns (bytes20 result) { + bytes2 oldValue = extract_20_2(self, offset); + assembly ("memory-safe") { + value := and(value, shl(240, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_20_4(bytes20 self, uint8 offset) internal pure returns (bytes4 result) { + if (offset > 16) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(224, not(0))) + } + } + + function replace_20_4(bytes20 self, bytes4 value, uint8 offset) internal pure returns (bytes20 result) { + bytes4 oldValue = extract_20_4(self, offset); + assembly ("memory-safe") { + value := and(value, shl(224, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_20_6(bytes20 self, uint8 offset) internal pure returns (bytes6 result) { + if (offset > 14) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(208, not(0))) + } + } + + function replace_20_6(bytes20 self, bytes6 value, uint8 offset) internal pure returns (bytes20 result) { + bytes6 oldValue = extract_20_6(self, offset); + assembly ("memory-safe") { + value := and(value, shl(208, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_20_8(bytes20 self, uint8 offset) internal pure returns (bytes8 result) { + if (offset > 12) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(192, not(0))) + } + } + + function replace_20_8(bytes20 self, bytes8 value, uint8 offset) internal pure returns (bytes20 result) { + bytes8 oldValue = extract_20_8(self, offset); + assembly ("memory-safe") { + value := and(value, shl(192, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_20_10(bytes20 self, uint8 offset) internal pure returns (bytes10 result) { + if (offset > 10) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(176, not(0))) + } + } + + function replace_20_10(bytes20 self, bytes10 value, uint8 offset) internal pure returns (bytes20 result) { + bytes10 oldValue = extract_20_10(self, offset); + assembly ("memory-safe") { + value := and(value, shl(176, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_20_12(bytes20 self, uint8 offset) internal pure returns (bytes12 result) { + if (offset > 8) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(160, not(0))) + } + } + + function replace_20_12(bytes20 self, bytes12 value, uint8 offset) internal pure returns (bytes20 result) { + bytes12 oldValue = extract_20_12(self, offset); + assembly ("memory-safe") { + value := and(value, shl(160, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_20_16(bytes20 self, uint8 offset) internal pure returns (bytes16 result) { + if (offset > 4) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(128, not(0))) + } + } + + function replace_20_16(bytes20 self, bytes16 value, uint8 offset) internal pure returns (bytes20 result) { + bytes16 oldValue = extract_20_16(self, offset); + assembly ("memory-safe") { + value := and(value, shl(128, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_22_1(bytes22 self, uint8 offset) internal pure returns (bytes1 result) { + if (offset > 21) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(248, not(0))) + } + } + + function replace_22_1(bytes22 self, bytes1 value, uint8 offset) internal pure returns (bytes22 result) { + bytes1 oldValue = extract_22_1(self, offset); + assembly ("memory-safe") { + value := and(value, shl(248, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_22_2(bytes22 self, uint8 offset) internal pure returns (bytes2 result) { + if (offset > 20) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(240, not(0))) + } + } + + function replace_22_2(bytes22 self, bytes2 value, uint8 offset) internal pure returns (bytes22 result) { + bytes2 oldValue = extract_22_2(self, offset); + assembly ("memory-safe") { + value := and(value, shl(240, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_22_4(bytes22 self, uint8 offset) internal pure returns (bytes4 result) { + if (offset > 18) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(224, not(0))) + } + } + + function replace_22_4(bytes22 self, bytes4 value, uint8 offset) internal pure returns (bytes22 result) { + bytes4 oldValue = extract_22_4(self, offset); + assembly ("memory-safe") { + value := and(value, shl(224, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_22_6(bytes22 self, uint8 offset) internal pure returns (bytes6 result) { + if (offset > 16) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(208, not(0))) + } + } + + function replace_22_6(bytes22 self, bytes6 value, uint8 offset) internal pure returns (bytes22 result) { + bytes6 oldValue = extract_22_6(self, offset); + assembly ("memory-safe") { + value := and(value, shl(208, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_22_8(bytes22 self, uint8 offset) internal pure returns (bytes8 result) { + if (offset > 14) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(192, not(0))) + } + } + + function replace_22_8(bytes22 self, bytes8 value, uint8 offset) internal pure returns (bytes22 result) { + bytes8 oldValue = extract_22_8(self, offset); + assembly ("memory-safe") { + value := and(value, shl(192, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_22_10(bytes22 self, uint8 offset) internal pure returns (bytes10 result) { + if (offset > 12) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(176, not(0))) + } + } + + function replace_22_10(bytes22 self, bytes10 value, uint8 offset) internal pure returns (bytes22 result) { + bytes10 oldValue = extract_22_10(self, offset); + assembly ("memory-safe") { + value := and(value, shl(176, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_22_12(bytes22 self, uint8 offset) internal pure returns (bytes12 result) { + if (offset > 10) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(160, not(0))) + } + } + + function replace_22_12(bytes22 self, bytes12 value, uint8 offset) internal pure returns (bytes22 result) { + bytes12 oldValue = extract_22_12(self, offset); + assembly ("memory-safe") { + value := and(value, shl(160, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_22_16(bytes22 self, uint8 offset) internal pure returns (bytes16 result) { + if (offset > 6) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(128, not(0))) + } + } + + function replace_22_16(bytes22 self, bytes16 value, uint8 offset) internal pure returns (bytes22 result) { + bytes16 oldValue = extract_22_16(self, offset); + assembly ("memory-safe") { + value := and(value, shl(128, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_22_20(bytes22 self, uint8 offset) internal pure returns (bytes20 result) { + if (offset > 2) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(96, not(0))) + } + } + + function replace_22_20(bytes22 self, bytes20 value, uint8 offset) internal pure returns (bytes22 result) { + bytes20 oldValue = extract_22_20(self, offset); + assembly ("memory-safe") { + value := and(value, shl(96, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_24_1(bytes24 self, uint8 offset) internal pure returns (bytes1 result) { + if (offset > 23) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(248, not(0))) + } + } + + function replace_24_1(bytes24 self, bytes1 value, uint8 offset) internal pure returns (bytes24 result) { + bytes1 oldValue = extract_24_1(self, offset); + assembly ("memory-safe") { + value := and(value, shl(248, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_24_2(bytes24 self, uint8 offset) internal pure returns (bytes2 result) { + if (offset > 22) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(240, not(0))) + } + } + + function replace_24_2(bytes24 self, bytes2 value, uint8 offset) internal pure returns (bytes24 result) { + bytes2 oldValue = extract_24_2(self, offset); + assembly ("memory-safe") { + value := and(value, shl(240, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_24_4(bytes24 self, uint8 offset) internal pure returns (bytes4 result) { + if (offset > 20) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(224, not(0))) + } + } + + function replace_24_4(bytes24 self, bytes4 value, uint8 offset) internal pure returns (bytes24 result) { + bytes4 oldValue = extract_24_4(self, offset); + assembly ("memory-safe") { + value := and(value, shl(224, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_24_6(bytes24 self, uint8 offset) internal pure returns (bytes6 result) { + if (offset > 18) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(208, not(0))) + } + } + + function replace_24_6(bytes24 self, bytes6 value, uint8 offset) internal pure returns (bytes24 result) { + bytes6 oldValue = extract_24_6(self, offset); + assembly ("memory-safe") { + value := and(value, shl(208, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_24_8(bytes24 self, uint8 offset) internal pure returns (bytes8 result) { + if (offset > 16) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(192, not(0))) + } + } + + function replace_24_8(bytes24 self, bytes8 value, uint8 offset) internal pure returns (bytes24 result) { + bytes8 oldValue = extract_24_8(self, offset); + assembly ("memory-safe") { + value := and(value, shl(192, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_24_10(bytes24 self, uint8 offset) internal pure returns (bytes10 result) { + if (offset > 14) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(176, not(0))) + } + } + + function replace_24_10(bytes24 self, bytes10 value, uint8 offset) internal pure returns (bytes24 result) { + bytes10 oldValue = extract_24_10(self, offset); + assembly ("memory-safe") { + value := and(value, shl(176, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_24_12(bytes24 self, uint8 offset) internal pure returns (bytes12 result) { + if (offset > 12) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(160, not(0))) + } + } + + function replace_24_12(bytes24 self, bytes12 value, uint8 offset) internal pure returns (bytes24 result) { + bytes12 oldValue = extract_24_12(self, offset); + assembly ("memory-safe") { + value := and(value, shl(160, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_24_16(bytes24 self, uint8 offset) internal pure returns (bytes16 result) { + if (offset > 8) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(128, not(0))) + } + } + + function replace_24_16(bytes24 self, bytes16 value, uint8 offset) internal pure returns (bytes24 result) { + bytes16 oldValue = extract_24_16(self, offset); + assembly ("memory-safe") { + value := and(value, shl(128, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_24_20(bytes24 self, uint8 offset) internal pure returns (bytes20 result) { + if (offset > 4) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(96, not(0))) + } + } + + function replace_24_20(bytes24 self, bytes20 value, uint8 offset) internal pure returns (bytes24 result) { + bytes20 oldValue = extract_24_20(self, offset); + assembly ("memory-safe") { + value := and(value, shl(96, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_24_22(bytes24 self, uint8 offset) internal pure returns (bytes22 result) { + if (offset > 2) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(80, not(0))) + } + } + + function replace_24_22(bytes24 self, bytes22 value, uint8 offset) internal pure returns (bytes24 result) { + bytes22 oldValue = extract_24_22(self, offset); + assembly ("memory-safe") { + value := and(value, shl(80, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_28_1(bytes28 self, uint8 offset) internal pure returns (bytes1 result) { + if (offset > 27) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(248, not(0))) + } + } + + function replace_28_1(bytes28 self, bytes1 value, uint8 offset) internal pure returns (bytes28 result) { + bytes1 oldValue = extract_28_1(self, offset); + assembly ("memory-safe") { + value := and(value, shl(248, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_28_2(bytes28 self, uint8 offset) internal pure returns (bytes2 result) { + if (offset > 26) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(240, not(0))) + } + } + + function replace_28_2(bytes28 self, bytes2 value, uint8 offset) internal pure returns (bytes28 result) { + bytes2 oldValue = extract_28_2(self, offset); + assembly ("memory-safe") { + value := and(value, shl(240, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_28_4(bytes28 self, uint8 offset) internal pure returns (bytes4 result) { + if (offset > 24) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(224, not(0))) + } + } + + function replace_28_4(bytes28 self, bytes4 value, uint8 offset) internal pure returns (bytes28 result) { + bytes4 oldValue = extract_28_4(self, offset); + assembly ("memory-safe") { + value := and(value, shl(224, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_28_6(bytes28 self, uint8 offset) internal pure returns (bytes6 result) { + if (offset > 22) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(208, not(0))) + } + } + + function replace_28_6(bytes28 self, bytes6 value, uint8 offset) internal pure returns (bytes28 result) { + bytes6 oldValue = extract_28_6(self, offset); + assembly ("memory-safe") { + value := and(value, shl(208, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_28_8(bytes28 self, uint8 offset) internal pure returns (bytes8 result) { + if (offset > 20) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(192, not(0))) + } + } + + function replace_28_8(bytes28 self, bytes8 value, uint8 offset) internal pure returns (bytes28 result) { + bytes8 oldValue = extract_28_8(self, offset); + assembly ("memory-safe") { + value := and(value, shl(192, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_28_10(bytes28 self, uint8 offset) internal pure returns (bytes10 result) { + if (offset > 18) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(176, not(0))) + } + } + + function replace_28_10(bytes28 self, bytes10 value, uint8 offset) internal pure returns (bytes28 result) { + bytes10 oldValue = extract_28_10(self, offset); + assembly ("memory-safe") { + value := and(value, shl(176, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_28_12(bytes28 self, uint8 offset) internal pure returns (bytes12 result) { + if (offset > 16) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(160, not(0))) + } + } + + function replace_28_12(bytes28 self, bytes12 value, uint8 offset) internal pure returns (bytes28 result) { + bytes12 oldValue = extract_28_12(self, offset); + assembly ("memory-safe") { + value := and(value, shl(160, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_28_16(bytes28 self, uint8 offset) internal pure returns (bytes16 result) { + if (offset > 12) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(128, not(0))) + } + } + + function replace_28_16(bytes28 self, bytes16 value, uint8 offset) internal pure returns (bytes28 result) { + bytes16 oldValue = extract_28_16(self, offset); + assembly ("memory-safe") { + value := and(value, shl(128, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_28_20(bytes28 self, uint8 offset) internal pure returns (bytes20 result) { + if (offset > 8) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(96, not(0))) + } + } + + function replace_28_20(bytes28 self, bytes20 value, uint8 offset) internal pure returns (bytes28 result) { + bytes20 oldValue = extract_28_20(self, offset); + assembly ("memory-safe") { + value := and(value, shl(96, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_28_22(bytes28 self, uint8 offset) internal pure returns (bytes22 result) { + if (offset > 6) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(80, not(0))) + } + } + + function replace_28_22(bytes28 self, bytes22 value, uint8 offset) internal pure returns (bytes28 result) { + bytes22 oldValue = extract_28_22(self, offset); + assembly ("memory-safe") { + value := and(value, shl(80, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_28_24(bytes28 self, uint8 offset) internal pure returns (bytes24 result) { + if (offset > 4) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(64, not(0))) + } + } + + function replace_28_24(bytes28 self, bytes24 value, uint8 offset) internal pure returns (bytes28 result) { + bytes24 oldValue = extract_28_24(self, offset); + assembly ("memory-safe") { + value := and(value, shl(64, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_32_1(bytes32 self, uint8 offset) internal pure returns (bytes1 result) { + if (offset > 31) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(248, not(0))) + } + } + + function replace_32_1(bytes32 self, bytes1 value, uint8 offset) internal pure returns (bytes32 result) { + bytes1 oldValue = extract_32_1(self, offset); + assembly ("memory-safe") { + value := and(value, shl(248, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_32_2(bytes32 self, uint8 offset) internal pure returns (bytes2 result) { + if (offset > 30) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(240, not(0))) + } + } + + function replace_32_2(bytes32 self, bytes2 value, uint8 offset) internal pure returns (bytes32 result) { + bytes2 oldValue = extract_32_2(self, offset); + assembly ("memory-safe") { + value := and(value, shl(240, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_32_4(bytes32 self, uint8 offset) internal pure returns (bytes4 result) { + if (offset > 28) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(224, not(0))) + } + } + + function replace_32_4(bytes32 self, bytes4 value, uint8 offset) internal pure returns (bytes32 result) { + bytes4 oldValue = extract_32_4(self, offset); + assembly ("memory-safe") { + value := and(value, shl(224, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_32_6(bytes32 self, uint8 offset) internal pure returns (bytes6 result) { + if (offset > 26) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(208, not(0))) + } + } + + function replace_32_6(bytes32 self, bytes6 value, uint8 offset) internal pure returns (bytes32 result) { + bytes6 oldValue = extract_32_6(self, offset); + assembly ("memory-safe") { + value := and(value, shl(208, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_32_8(bytes32 self, uint8 offset) internal pure returns (bytes8 result) { + if (offset > 24) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(192, not(0))) + } + } + + function replace_32_8(bytes32 self, bytes8 value, uint8 offset) internal pure returns (bytes32 result) { + bytes8 oldValue = extract_32_8(self, offset); + assembly ("memory-safe") { + value := and(value, shl(192, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_32_10(bytes32 self, uint8 offset) internal pure returns (bytes10 result) { + if (offset > 22) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(176, not(0))) + } + } + + function replace_32_10(bytes32 self, bytes10 value, uint8 offset) internal pure returns (bytes32 result) { + bytes10 oldValue = extract_32_10(self, offset); + assembly ("memory-safe") { + value := and(value, shl(176, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_32_12(bytes32 self, uint8 offset) internal pure returns (bytes12 result) { + if (offset > 20) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(160, not(0))) + } + } + + function replace_32_12(bytes32 self, bytes12 value, uint8 offset) internal pure returns (bytes32 result) { + bytes12 oldValue = extract_32_12(self, offset); + assembly ("memory-safe") { + value := and(value, shl(160, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_32_16(bytes32 self, uint8 offset) internal pure returns (bytes16 result) { + if (offset > 16) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(128, not(0))) + } + } + + function replace_32_16(bytes32 self, bytes16 value, uint8 offset) internal pure returns (bytes32 result) { + bytes16 oldValue = extract_32_16(self, offset); + assembly ("memory-safe") { + value := and(value, shl(128, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_32_20(bytes32 self, uint8 offset) internal pure returns (bytes20 result) { + if (offset > 12) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(96, not(0))) + } + } + + function replace_32_20(bytes32 self, bytes20 value, uint8 offset) internal pure returns (bytes32 result) { + bytes20 oldValue = extract_32_20(self, offset); + assembly ("memory-safe") { + value := and(value, shl(96, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_32_22(bytes32 self, uint8 offset) internal pure returns (bytes22 result) { + if (offset > 10) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(80, not(0))) + } + } + + function replace_32_22(bytes32 self, bytes22 value, uint8 offset) internal pure returns (bytes32 result) { + bytes22 oldValue = extract_32_22(self, offset); + assembly ("memory-safe") { + value := and(value, shl(80, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_32_24(bytes32 self, uint8 offset) internal pure returns (bytes24 result) { + if (offset > 8) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(64, not(0))) + } + } + + function replace_32_24(bytes32 self, bytes24 value, uint8 offset) internal pure returns (bytes32 result) { + bytes24 oldValue = extract_32_24(self, offset); + assembly ("memory-safe") { + value := and(value, shl(64, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } + + function extract_32_28(bytes32 self, uint8 offset) internal pure returns (bytes28 result) { + if (offset > 4) revert OutOfRangeAccess(); + assembly ("memory-safe") { + result := and(shl(mul(8, offset), self), shl(32, not(0))) + } + } + + function replace_32_28(bytes32 self, bytes28 value, uint8 offset) internal pure returns (bytes32 result) { + bytes28 oldValue = extract_32_28(self, offset); + assembly ("memory-safe") { + value := and(value, shl(32, not(0))) + result := xor(self, shr(mul(8, offset), xor(oldValue, value))) + } + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/utils/Panic.sol b/dependencies/@openzeppelin-contracts-5.4.0/utils/Panic.sol new file mode 100644 index 00000000..e168824d --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/utils/Panic.sol @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.1.0) (utils/Panic.sol) + +pragma solidity ^0.8.20; + +/** + * @dev Helper library for emitting standardized panic codes. + * + * ```solidity + * contract Example { + * using Panic for uint256; + * + * // Use any of the declared internal constants + * function foo() { Panic.GENERIC.panic(); } + * + * // Alternatively + * function foo() { Panic.panic(Panic.GENERIC); } + * } + * ``` + * + * Follows the list from https://github.com/ethereum/solidity/blob/v0.8.24/libsolutil/ErrorCodes.h[libsolutil]. + * + * _Available since v5.1._ + */ +// slither-disable-next-line unused-state +library Panic { + /// @dev generic / unspecified error + uint256 internal constant GENERIC = 0x00; + /// @dev used by the assert() builtin + uint256 internal constant ASSERT = 0x01; + /// @dev arithmetic underflow or overflow + uint256 internal constant UNDER_OVERFLOW = 0x11; + /// @dev division or modulo by zero + uint256 internal constant DIVISION_BY_ZERO = 0x12; + /// @dev enum conversion error + uint256 internal constant ENUM_CONVERSION_ERROR = 0x21; + /// @dev invalid encoding in storage + uint256 internal constant STORAGE_ENCODING_ERROR = 0x22; + /// @dev empty array pop + uint256 internal constant EMPTY_ARRAY_POP = 0x31; + /// @dev array out of bounds access + uint256 internal constant ARRAY_OUT_OF_BOUNDS = 0x32; + /// @dev resource error (too large allocation or too large array) + uint256 internal constant RESOURCE_ERROR = 0x41; + /// @dev calling invalid internal function + uint256 internal constant INVALID_INTERNAL_FUNCTION = 0x51; + + /// @dev Reverts with a panic code. Recommended to use with + /// the internal constants with predefined codes. + function panic(uint256 code) internal pure { + assembly ("memory-safe") { + mstore(0x00, 0x4e487b71) + mstore(0x20, code) + revert(0x1c, 0x24) + } + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/utils/Pausable.sol b/dependencies/@openzeppelin-contracts-5.4.0/utils/Pausable.sol new file mode 100644 index 00000000..68e7d268 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/utils/Pausable.sol @@ -0,0 +1,112 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.3.0) (utils/Pausable.sol) + +pragma solidity ^0.8.20; + +import {Context} from "../utils/Context.sol"; + +/** + * @dev Contract module which allows children to implement an emergency stop + * mechanism that can be triggered by an authorized account. + * + * This module is used through inheritance. It will make available the + * modifiers `whenNotPaused` and `whenPaused`, which can be applied to + * the functions of your contract. Note that they will not be pausable by + * simply including this module, only once the modifiers are put in place. + */ +abstract contract Pausable is Context { + bool private _paused; + + /** + * @dev Emitted when the pause is triggered by `account`. + */ + event Paused(address account); + + /** + * @dev Emitted when the pause is lifted by `account`. + */ + event Unpaused(address account); + + /** + * @dev The operation failed because the contract is paused. + */ + error EnforcedPause(); + + /** + * @dev The operation failed because the contract is not paused. + */ + error ExpectedPause(); + + /** + * @dev Modifier to make a function callable only when the contract is not paused. + * + * Requirements: + * + * - The contract must not be paused. + */ + modifier whenNotPaused() { + _requireNotPaused(); + _; + } + + /** + * @dev Modifier to make a function callable only when the contract is paused. + * + * Requirements: + * + * - The contract must be paused. + */ + modifier whenPaused() { + _requirePaused(); + _; + } + + /** + * @dev Returns true if the contract is paused, and false otherwise. + */ + function paused() public view virtual returns (bool) { + return _paused; + } + + /** + * @dev Throws if the contract is paused. + */ + function _requireNotPaused() internal view virtual { + if (paused()) { + revert EnforcedPause(); + } + } + + /** + * @dev Throws if the contract is not paused. + */ + function _requirePaused() internal view virtual { + if (!paused()) { + revert ExpectedPause(); + } + } + + /** + * @dev Triggers stopped state. + * + * Requirements: + * + * - The contract must not be paused. + */ + function _pause() internal virtual whenNotPaused { + _paused = true; + emit Paused(_msgSender()); + } + + /** + * @dev Returns to normal state. + * + * Requirements: + * + * - The contract must be paused. + */ + function _unpause() internal virtual whenPaused { + _paused = false; + emit Unpaused(_msgSender()); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/utils/ReentrancyGuard.sol b/dependencies/@openzeppelin-contracts-5.4.0/utils/ReentrancyGuard.sol new file mode 100644 index 00000000..a95fb512 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/utils/ReentrancyGuard.sol @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.1.0) (utils/ReentrancyGuard.sol) + +pragma solidity ^0.8.20; + +/** + * @dev Contract module that helps prevent reentrant calls to a function. + * + * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier + * available, which can be applied to functions to make sure there are no nested + * (reentrant) calls to them. + * + * Note that because there is a single `nonReentrant` guard, functions marked as + * `nonReentrant` may not call one another. This can be worked around by making + * those functions `private`, and then adding `external` `nonReentrant` entry + * points to them. + * + * TIP: If EIP-1153 (transient storage) is available on the chain you're deploying at, + * consider using {ReentrancyGuardTransient} instead. + * + * TIP: If you would like to learn more about reentrancy and alternative ways + * to protect against it, check out our blog post + * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. + */ +abstract contract ReentrancyGuard { + // Booleans are more expensive than uint256 or any type that takes up a full + // word because each write operation emits an extra SLOAD to first read the + // slot's contents, replace the bits taken up by the boolean, and then write + // back. This is the compiler's defense against contract upgrades and + // pointer aliasing, and it cannot be disabled. + + // The values being non-zero value makes deployment a bit more expensive, + // but in exchange the refund on every call to nonReentrant will be lower in + // amount. Since refunds are capped to a percentage of the total + // transaction's gas, it is best to keep them low in cases like this one, to + // increase the likelihood of the full refund coming into effect. + uint256 private constant NOT_ENTERED = 1; + uint256 private constant ENTERED = 2; + + uint256 private _status; + + /** + * @dev Unauthorized reentrant call. + */ + error ReentrancyGuardReentrantCall(); + + constructor() { + _status = NOT_ENTERED; + } + + /** + * @dev Prevents a contract from calling itself, directly or indirectly. + * Calling a `nonReentrant` function from another `nonReentrant` + * function is not supported. It is possible to prevent this from happening + * by making the `nonReentrant` function external, and making it call a + * `private` function that does the actual work. + */ + modifier nonReentrant() { + _nonReentrantBefore(); + _; + _nonReentrantAfter(); + } + + function _nonReentrantBefore() private { + // On the first call to nonReentrant, _status will be NOT_ENTERED + if (_status == ENTERED) { + revert ReentrancyGuardReentrantCall(); + } + + // Any calls to nonReentrant after this point will fail + _status = ENTERED; + } + + function _nonReentrantAfter() private { + // By storing the original value once again, a refund is triggered (see + // https://eips.ethereum.org/EIPS/eip-2200) + _status = NOT_ENTERED; + } + + /** + * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a + * `nonReentrant` function in the call stack. + */ + function _reentrancyGuardEntered() internal view returns (bool) { + return _status == ENTERED; + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/utils/ReentrancyGuardTransient.sol b/dependencies/@openzeppelin-contracts-5.4.0/utils/ReentrancyGuardTransient.sol new file mode 100644 index 00000000..a1318c86 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/utils/ReentrancyGuardTransient.sol @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.3.0) (utils/ReentrancyGuardTransient.sol) + +pragma solidity ^0.8.24; + +import {TransientSlot} from "./TransientSlot.sol"; + +/** + * @dev Variant of {ReentrancyGuard} that uses transient storage. + * + * NOTE: This variant only works on networks where EIP-1153 is available. + * + * _Available since v5.1._ + */ +abstract contract ReentrancyGuardTransient { + using TransientSlot for *; + + // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.ReentrancyGuard")) - 1)) & ~bytes32(uint256(0xff)) + bytes32 private constant REENTRANCY_GUARD_STORAGE = + 0x9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00; + + /** + * @dev Unauthorized reentrant call. + */ + error ReentrancyGuardReentrantCall(); + + /** + * @dev Prevents a contract from calling itself, directly or indirectly. + * Calling a `nonReentrant` function from another `nonReentrant` + * function is not supported. It is possible to prevent this from happening + * by making the `nonReentrant` function external, and making it call a + * `private` function that does the actual work. + */ + modifier nonReentrant() { + _nonReentrantBefore(); + _; + _nonReentrantAfter(); + } + + function _nonReentrantBefore() private { + // On the first call to nonReentrant, REENTRANCY_GUARD_STORAGE.asBoolean().tload() will be false + if (_reentrancyGuardEntered()) { + revert ReentrancyGuardReentrantCall(); + } + + // Any calls to nonReentrant after this point will fail + REENTRANCY_GUARD_STORAGE.asBoolean().tstore(true); + } + + function _nonReentrantAfter() private { + REENTRANCY_GUARD_STORAGE.asBoolean().tstore(false); + } + + /** + * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a + * `nonReentrant` function in the call stack. + */ + function _reentrancyGuardEntered() internal view returns (bool) { + return REENTRANCY_GUARD_STORAGE.asBoolean().tload(); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/utils/ShortStrings.sol b/dependencies/@openzeppelin-contracts-5.4.0/utils/ShortStrings.sol new file mode 100644 index 00000000..81d713d4 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/utils/ShortStrings.sol @@ -0,0 +1,122 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.3.0) (utils/ShortStrings.sol) + +pragma solidity ^0.8.20; + +import {StorageSlot} from "./StorageSlot.sol"; + +// | string | 0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA | +// | length | 0x BB | +type ShortString is bytes32; + +/** + * @dev This library provides functions to convert short memory strings + * into a `ShortString` type that can be used as an immutable variable. + * + * Strings of arbitrary length can be optimized using this library if + * they are short enough (up to 31 bytes) by packing them with their + * length (1 byte) in a single EVM word (32 bytes). Additionally, a + * fallback mechanism can be used for every other case. + * + * Usage example: + * + * ```solidity + * contract Named { + * using ShortStrings for *; + * + * ShortString private immutable _name; + * string private _nameFallback; + * + * constructor(string memory contractName) { + * _name = contractName.toShortStringWithFallback(_nameFallback); + * } + * + * function name() external view returns (string memory) { + * return _name.toStringWithFallback(_nameFallback); + * } + * } + * ``` + */ +library ShortStrings { + // Used as an identifier for strings longer than 31 bytes. + bytes32 private constant FALLBACK_SENTINEL = 0x00000000000000000000000000000000000000000000000000000000000000FF; + + error StringTooLong(string str); + error InvalidShortString(); + + /** + * @dev Encode a string of at most 31 chars into a `ShortString`. + * + * This will trigger a `StringTooLong` error is the input string is too long. + */ + function toShortString(string memory str) internal pure returns (ShortString) { + bytes memory bstr = bytes(str); + if (bstr.length > 31) { + revert StringTooLong(str); + } + return ShortString.wrap(bytes32(uint256(bytes32(bstr)) | bstr.length)); + } + + /** + * @dev Decode a `ShortString` back to a "normal" string. + */ + function toString(ShortString sstr) internal pure returns (string memory) { + uint256 len = byteLength(sstr); + // using `new string(len)` would work locally but is not memory safe. + string memory str = new string(32); + assembly ("memory-safe") { + mstore(str, len) + mstore(add(str, 0x20), sstr) + } + return str; + } + + /** + * @dev Return the length of a `ShortString`. + */ + function byteLength(ShortString sstr) internal pure returns (uint256) { + uint256 result = uint256(ShortString.unwrap(sstr)) & 0xFF; + if (result > 31) { + revert InvalidShortString(); + } + return result; + } + + /** + * @dev Encode a string into a `ShortString`, or write it to storage if it is too long. + */ + function toShortStringWithFallback(string memory value, string storage store) internal returns (ShortString) { + if (bytes(value).length < 32) { + return toShortString(value); + } else { + StorageSlot.getStringSlot(store).value = value; + return ShortString.wrap(FALLBACK_SENTINEL); + } + } + + /** + * @dev Decode a string that was encoded to `ShortString` or written to storage using {toShortStringWithFallback}. + */ + function toStringWithFallback(ShortString value, string storage store) internal pure returns (string memory) { + if (ShortString.unwrap(value) != FALLBACK_SENTINEL) { + return toString(value); + } else { + return store; + } + } + + /** + * @dev Return the length of a string that was encoded to `ShortString` or written to storage using + * {toShortStringWithFallback}. + * + * WARNING: This will return the "byte length" of the string. This may not reflect the actual length in terms of + * actual characters as the UTF-8 encoding of a single character can span over multiple bytes. + */ + function byteLengthWithFallback(ShortString value, string storage store) internal view returns (uint256) { + if (ShortString.unwrap(value) != FALLBACK_SENTINEL) { + return byteLength(value); + } else { + return bytes(store).length; + } + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/utils/SlotDerivation.sol b/dependencies/@openzeppelin-contracts-5.4.0/utils/SlotDerivation.sol new file mode 100644 index 00000000..df23efa2 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/utils/SlotDerivation.sol @@ -0,0 +1,155 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.3.0) (utils/SlotDerivation.sol) +// This file was procedurally generated from scripts/generate/templates/SlotDerivation.js. + +pragma solidity ^0.8.20; + +/** + * @dev Library for computing storage (and transient storage) locations from namespaces and deriving slots + * corresponding to standard patterns. The derivation method for array and mapping matches the storage layout used by + * the solidity language / compiler. + * + * See https://docs.soliditylang.org/en/v0.8.20/internals/layout_in_storage.html#mappings-and-dynamic-arrays[Solidity docs for mappings and dynamic arrays.]. + * + * Example usage: + * ```solidity + * contract Example { + * // Add the library methods + * using StorageSlot for bytes32; + * using SlotDerivation for bytes32; + * + * // Declare a namespace + * string private constant _NAMESPACE = ""; // eg. OpenZeppelin.Slot + * + * function setValueInNamespace(uint256 key, address newValue) internal { + * _NAMESPACE.erc7201Slot().deriveMapping(key).getAddressSlot().value = newValue; + * } + * + * function getValueInNamespace(uint256 key) internal view returns (address) { + * return _NAMESPACE.erc7201Slot().deriveMapping(key).getAddressSlot().value; + * } + * } + * ``` + * + * TIP: Consider using this library along with {StorageSlot}. + * + * NOTE: This library provides a way to manipulate storage locations in a non-standard way. Tooling for checking + * upgrade safety will ignore the slots accessed through this library. + * + * _Available since v5.1._ + */ +library SlotDerivation { + /** + * @dev Derive an ERC-7201 slot from a string (namespace). + */ + function erc7201Slot(string memory namespace) internal pure returns (bytes32 slot) { + assembly ("memory-safe") { + mstore(0x00, sub(keccak256(add(namespace, 0x20), mload(namespace)), 1)) + slot := and(keccak256(0x00, 0x20), not(0xff)) + } + } + + /** + * @dev Add an offset to a slot to get the n-th element of a structure or an array. + */ + function offset(bytes32 slot, uint256 pos) internal pure returns (bytes32 result) { + unchecked { + return bytes32(uint256(slot) + pos); + } + } + + /** + * @dev Derive the location of the first element in an array from the slot where the length is stored. + */ + function deriveArray(bytes32 slot) internal pure returns (bytes32 result) { + assembly ("memory-safe") { + mstore(0x00, slot) + result := keccak256(0x00, 0x20) + } + } + + /** + * @dev Derive the location of a mapping element from the key. + */ + function deriveMapping(bytes32 slot, address key) internal pure returns (bytes32 result) { + assembly ("memory-safe") { + mstore(0x00, and(key, shr(96, not(0)))) + mstore(0x20, slot) + result := keccak256(0x00, 0x40) + } + } + + /** + * @dev Derive the location of a mapping element from the key. + */ + function deriveMapping(bytes32 slot, bool key) internal pure returns (bytes32 result) { + assembly ("memory-safe") { + mstore(0x00, iszero(iszero(key))) + mstore(0x20, slot) + result := keccak256(0x00, 0x40) + } + } + + /** + * @dev Derive the location of a mapping element from the key. + */ + function deriveMapping(bytes32 slot, bytes32 key) internal pure returns (bytes32 result) { + assembly ("memory-safe") { + mstore(0x00, key) + mstore(0x20, slot) + result := keccak256(0x00, 0x40) + } + } + + /** + * @dev Derive the location of a mapping element from the key. + */ + function deriveMapping(bytes32 slot, uint256 key) internal pure returns (bytes32 result) { + assembly ("memory-safe") { + mstore(0x00, key) + mstore(0x20, slot) + result := keccak256(0x00, 0x40) + } + } + + /** + * @dev Derive the location of a mapping element from the key. + */ + function deriveMapping(bytes32 slot, int256 key) internal pure returns (bytes32 result) { + assembly ("memory-safe") { + mstore(0x00, key) + mstore(0x20, slot) + result := keccak256(0x00, 0x40) + } + } + + /** + * @dev Derive the location of a mapping element from the key. + */ + function deriveMapping(bytes32 slot, string memory key) internal pure returns (bytes32 result) { + assembly ("memory-safe") { + let length := mload(key) + let begin := add(key, 0x20) + let end := add(begin, length) + let cache := mload(end) + mstore(end, slot) + result := keccak256(begin, add(length, 0x20)) + mstore(end, cache) + } + } + + /** + * @dev Derive the location of a mapping element from the key. + */ + function deriveMapping(bytes32 slot, bytes memory key) internal pure returns (bytes32 result) { + assembly ("memory-safe") { + let length := mload(key) + let begin := add(key, 0x20) + let end := add(begin, length) + let cache := mload(end) + mstore(end, slot) + result := keccak256(begin, add(length, 0x20)) + mstore(end, cache) + } + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/utils/StorageSlot.sol b/dependencies/@openzeppelin-contracts-5.4.0/utils/StorageSlot.sol new file mode 100644 index 00000000..aebb1052 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/utils/StorageSlot.sol @@ -0,0 +1,143 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.1.0) (utils/StorageSlot.sol) +// This file was procedurally generated from scripts/generate/templates/StorageSlot.js. + +pragma solidity ^0.8.20; + +/** + * @dev Library for reading and writing primitive types to specific storage slots. + * + * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts. + * This library helps with reading and writing to such slots without the need for inline assembly. + * + * The functions in this library return Slot structs that contain a `value` member that can be used to read or write. + * + * Example usage to set ERC-1967 implementation slot: + * ```solidity + * contract ERC1967 { + * // Define the slot. Alternatively, use the SlotDerivation library to derive the slot. + * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; + * + * function _getImplementation() internal view returns (address) { + * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; + * } + * + * function _setImplementation(address newImplementation) internal { + * require(newImplementation.code.length > 0); + * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; + * } + * } + * ``` + * + * TIP: Consider using this library along with {SlotDerivation}. + */ +library StorageSlot { + struct AddressSlot { + address value; + } + + struct BooleanSlot { + bool value; + } + + struct Bytes32Slot { + bytes32 value; + } + + struct Uint256Slot { + uint256 value; + } + + struct Int256Slot { + int256 value; + } + + struct StringSlot { + string value; + } + + struct BytesSlot { + bytes value; + } + + /** + * @dev Returns an `AddressSlot` with member `value` located at `slot`. + */ + function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { + assembly ("memory-safe") { + r.slot := slot + } + } + + /** + * @dev Returns a `BooleanSlot` with member `value` located at `slot`. + */ + function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { + assembly ("memory-safe") { + r.slot := slot + } + } + + /** + * @dev Returns a `Bytes32Slot` with member `value` located at `slot`. + */ + function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { + assembly ("memory-safe") { + r.slot := slot + } + } + + /** + * @dev Returns a `Uint256Slot` with member `value` located at `slot`. + */ + function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { + assembly ("memory-safe") { + r.slot := slot + } + } + + /** + * @dev Returns a `Int256Slot` with member `value` located at `slot`. + */ + function getInt256Slot(bytes32 slot) internal pure returns (Int256Slot storage r) { + assembly ("memory-safe") { + r.slot := slot + } + } + + /** + * @dev Returns a `StringSlot` with member `value` located at `slot`. + */ + function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) { + assembly ("memory-safe") { + r.slot := slot + } + } + + /** + * @dev Returns an `StringSlot` representation of the string storage pointer `store`. + */ + function getStringSlot(string storage store) internal pure returns (StringSlot storage r) { + assembly ("memory-safe") { + r.slot := store.slot + } + } + + /** + * @dev Returns a `BytesSlot` with member `value` located at `slot`. + */ + function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) { + assembly ("memory-safe") { + r.slot := slot + } + } + + /** + * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`. + */ + function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) { + assembly ("memory-safe") { + r.slot := store.slot + } + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/utils/Strings.sol b/dependencies/@openzeppelin-contracts-5.4.0/utils/Strings.sol new file mode 100644 index 00000000..a2d934dd --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/utils/Strings.sol @@ -0,0 +1,490 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (utils/Strings.sol) + +pragma solidity ^0.8.20; + +import {Math} from "./math/Math.sol"; +import {SafeCast} from "./math/SafeCast.sol"; +import {SignedMath} from "./math/SignedMath.sol"; + +/** + * @dev String operations. + */ +library Strings { + using SafeCast for *; + + bytes16 private constant HEX_DIGITS = "0123456789abcdef"; + uint8 private constant ADDRESS_LENGTH = 20; + uint256 private constant SPECIAL_CHARS_LOOKUP = + (1 << 0x08) | // backspace + (1 << 0x09) | // tab + (1 << 0x0a) | // newline + (1 << 0x0c) | // form feed + (1 << 0x0d) | // carriage return + (1 << 0x22) | // double quote + (1 << 0x5c); // backslash + + /** + * @dev The `value` string doesn't fit in the specified `length`. + */ + error StringsInsufficientHexLength(uint256 value, uint256 length); + + /** + * @dev The string being parsed contains characters that are not in scope of the given base. + */ + error StringsInvalidChar(); + + /** + * @dev The string being parsed is not a properly formatted address. + */ + error StringsInvalidAddressFormat(); + + /** + * @dev Converts a `uint256` to its ASCII `string` decimal representation. + */ + function toString(uint256 value) internal pure returns (string memory) { + unchecked { + uint256 length = Math.log10(value) + 1; + string memory buffer = new string(length); + uint256 ptr; + assembly ("memory-safe") { + ptr := add(add(buffer, 0x20), length) + } + while (true) { + ptr--; + assembly ("memory-safe") { + mstore8(ptr, byte(mod(value, 10), HEX_DIGITS)) + } + value /= 10; + if (value == 0) break; + } + return buffer; + } + } + + /** + * @dev Converts a `int256` to its ASCII `string` decimal representation. + */ + function toStringSigned(int256 value) internal pure returns (string memory) { + return string.concat(value < 0 ? "-" : "", toString(SignedMath.abs(value))); + } + + /** + * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. + */ + function toHexString(uint256 value) internal pure returns (string memory) { + unchecked { + return toHexString(value, Math.log256(value) + 1); + } + } + + /** + * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. + */ + function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { + uint256 localValue = value; + bytes memory buffer = new bytes(2 * length + 2); + buffer[0] = "0"; + buffer[1] = "x"; + for (uint256 i = 2 * length + 1; i > 1; --i) { + buffer[i] = HEX_DIGITS[localValue & 0xf]; + localValue >>= 4; + } + if (localValue != 0) { + revert StringsInsufficientHexLength(value, length); + } + return string(buffer); + } + + /** + * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal + * representation. + */ + function toHexString(address addr) internal pure returns (string memory) { + return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH); + } + + /** + * @dev Converts an `address` with fixed length of 20 bytes to its checksummed ASCII `string` hexadecimal + * representation, according to EIP-55. + */ + function toChecksumHexString(address addr) internal pure returns (string memory) { + bytes memory buffer = bytes(toHexString(addr)); + + // hash the hex part of buffer (skip length + 2 bytes, length 40) + uint256 hashValue; + assembly ("memory-safe") { + hashValue := shr(96, keccak256(add(buffer, 0x22), 40)) + } + + for (uint256 i = 41; i > 1; --i) { + // possible values for buffer[i] are 48 (0) to 57 (9) and 97 (a) to 102 (f) + if (hashValue & 0xf > 7 && uint8(buffer[i]) > 96) { + // case shift by xoring with 0x20 + buffer[i] ^= 0x20; + } + hashValue >>= 4; + } + return string(buffer); + } + + /** + * @dev Returns true if the two strings are equal. + */ + function equal(string memory a, string memory b) internal pure returns (bool) { + return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b)); + } + + /** + * @dev Parse a decimal string and returns the value as a `uint256`. + * + * Requirements: + * - The string must be formatted as `[0-9]*` + * - The result must fit into an `uint256` type + */ + function parseUint(string memory input) internal pure returns (uint256) { + return parseUint(input, 0, bytes(input).length); + } + + /** + * @dev Variant of {parseUint-string} that parses a substring of `input` located between position `begin` (included) and + * `end` (excluded). + * + * Requirements: + * - The substring must be formatted as `[0-9]*` + * - The result must fit into an `uint256` type + */ + function parseUint(string memory input, uint256 begin, uint256 end) internal pure returns (uint256) { + (bool success, uint256 value) = tryParseUint(input, begin, end); + if (!success) revert StringsInvalidChar(); + return value; + } + + /** + * @dev Variant of {parseUint-string} that returns false if the parsing fails because of an invalid character. + * + * NOTE: This function will revert if the result does not fit in a `uint256`. + */ + function tryParseUint(string memory input) internal pure returns (bool success, uint256 value) { + return _tryParseUintUncheckedBounds(input, 0, bytes(input).length); + } + + /** + * @dev Variant of {parseUint-string-uint256-uint256} that returns false if the parsing fails because of an invalid + * character. + * + * NOTE: This function will revert if the result does not fit in a `uint256`. + */ + function tryParseUint( + string memory input, + uint256 begin, + uint256 end + ) internal pure returns (bool success, uint256 value) { + if (end > bytes(input).length || begin > end) return (false, 0); + return _tryParseUintUncheckedBounds(input, begin, end); + } + + /** + * @dev Implementation of {tryParseUint-string-uint256-uint256} that does not check bounds. Caller should make sure that + * `begin <= end <= input.length`. Other inputs would result in undefined behavior. + */ + function _tryParseUintUncheckedBounds( + string memory input, + uint256 begin, + uint256 end + ) private pure returns (bool success, uint256 value) { + bytes memory buffer = bytes(input); + + uint256 result = 0; + for (uint256 i = begin; i < end; ++i) { + uint8 chr = _tryParseChr(bytes1(_unsafeReadBytesOffset(buffer, i))); + if (chr > 9) return (false, 0); + result *= 10; + result += chr; + } + return (true, result); + } + + /** + * @dev Parse a decimal string and returns the value as a `int256`. + * + * Requirements: + * - The string must be formatted as `[-+]?[0-9]*` + * - The result must fit in an `int256` type. + */ + function parseInt(string memory input) internal pure returns (int256) { + return parseInt(input, 0, bytes(input).length); + } + + /** + * @dev Variant of {parseInt-string} that parses a substring of `input` located between position `begin` (included) and + * `end` (excluded). + * + * Requirements: + * - The substring must be formatted as `[-+]?[0-9]*` + * - The result must fit in an `int256` type. + */ + function parseInt(string memory input, uint256 begin, uint256 end) internal pure returns (int256) { + (bool success, int256 value) = tryParseInt(input, begin, end); + if (!success) revert StringsInvalidChar(); + return value; + } + + /** + * @dev Variant of {parseInt-string} that returns false if the parsing fails because of an invalid character or if + * the result does not fit in a `int256`. + * + * NOTE: This function will revert if the absolute value of the result does not fit in a `uint256`. + */ + function tryParseInt(string memory input) internal pure returns (bool success, int256 value) { + return _tryParseIntUncheckedBounds(input, 0, bytes(input).length); + } + + uint256 private constant ABS_MIN_INT256 = 2 ** 255; + + /** + * @dev Variant of {parseInt-string-uint256-uint256} that returns false if the parsing fails because of an invalid + * character or if the result does not fit in a `int256`. + * + * NOTE: This function will revert if the absolute value of the result does not fit in a `uint256`. + */ + function tryParseInt( + string memory input, + uint256 begin, + uint256 end + ) internal pure returns (bool success, int256 value) { + if (end > bytes(input).length || begin > end) return (false, 0); + return _tryParseIntUncheckedBounds(input, begin, end); + } + + /** + * @dev Implementation of {tryParseInt-string-uint256-uint256} that does not check bounds. Caller should make sure that + * `begin <= end <= input.length`. Other inputs would result in undefined behavior. + */ + function _tryParseIntUncheckedBounds( + string memory input, + uint256 begin, + uint256 end + ) private pure returns (bool success, int256 value) { + bytes memory buffer = bytes(input); + + // Check presence of a negative sign. + bytes1 sign = begin == end ? bytes1(0) : bytes1(_unsafeReadBytesOffset(buffer, begin)); // don't do out-of-bound (possibly unsafe) read if sub-string is empty + bool positiveSign = sign == bytes1("+"); + bool negativeSign = sign == bytes1("-"); + uint256 offset = (positiveSign || negativeSign).toUint(); + + (bool absSuccess, uint256 absValue) = tryParseUint(input, begin + offset, end); + + if (absSuccess && absValue < ABS_MIN_INT256) { + return (true, negativeSign ? -int256(absValue) : int256(absValue)); + } else if (absSuccess && negativeSign && absValue == ABS_MIN_INT256) { + return (true, type(int256).min); + } else return (false, 0); + } + + /** + * @dev Parse a hexadecimal string (with or without "0x" prefix), and returns the value as a `uint256`. + * + * Requirements: + * - The string must be formatted as `(0x)?[0-9a-fA-F]*` + * - The result must fit in an `uint256` type. + */ + function parseHexUint(string memory input) internal pure returns (uint256) { + return parseHexUint(input, 0, bytes(input).length); + } + + /** + * @dev Variant of {parseHexUint-string} that parses a substring of `input` located between position `begin` (included) and + * `end` (excluded). + * + * Requirements: + * - The substring must be formatted as `(0x)?[0-9a-fA-F]*` + * - The result must fit in an `uint256` type. + */ + function parseHexUint(string memory input, uint256 begin, uint256 end) internal pure returns (uint256) { + (bool success, uint256 value) = tryParseHexUint(input, begin, end); + if (!success) revert StringsInvalidChar(); + return value; + } + + /** + * @dev Variant of {parseHexUint-string} that returns false if the parsing fails because of an invalid character. + * + * NOTE: This function will revert if the result does not fit in a `uint256`. + */ + function tryParseHexUint(string memory input) internal pure returns (bool success, uint256 value) { + return _tryParseHexUintUncheckedBounds(input, 0, bytes(input).length); + } + + /** + * @dev Variant of {parseHexUint-string-uint256-uint256} that returns false if the parsing fails because of an + * invalid character. + * + * NOTE: This function will revert if the result does not fit in a `uint256`. + */ + function tryParseHexUint( + string memory input, + uint256 begin, + uint256 end + ) internal pure returns (bool success, uint256 value) { + if (end > bytes(input).length || begin > end) return (false, 0); + return _tryParseHexUintUncheckedBounds(input, begin, end); + } + + /** + * @dev Implementation of {tryParseHexUint-string-uint256-uint256} that does not check bounds. Caller should make sure that + * `begin <= end <= input.length`. Other inputs would result in undefined behavior. + */ + function _tryParseHexUintUncheckedBounds( + string memory input, + uint256 begin, + uint256 end + ) private pure returns (bool success, uint256 value) { + bytes memory buffer = bytes(input); + + // skip 0x prefix if present + bool hasPrefix = (end > begin + 1) && bytes2(_unsafeReadBytesOffset(buffer, begin)) == bytes2("0x"); // don't do out-of-bound (possibly unsafe) read if sub-string is empty + uint256 offset = hasPrefix.toUint() * 2; + + uint256 result = 0; + for (uint256 i = begin + offset; i < end; ++i) { + uint8 chr = _tryParseChr(bytes1(_unsafeReadBytesOffset(buffer, i))); + if (chr > 15) return (false, 0); + result *= 16; + unchecked { + // Multiplying by 16 is equivalent to a shift of 4 bits (with additional overflow check). + // This guarantees that adding a value < 16 will not cause an overflow, hence the unchecked. + result += chr; + } + } + return (true, result); + } + + /** + * @dev Parse a hexadecimal string (with or without "0x" prefix), and returns the value as an `address`. + * + * Requirements: + * - The string must be formatted as `(0x)?[0-9a-fA-F]{40}` + */ + function parseAddress(string memory input) internal pure returns (address) { + return parseAddress(input, 0, bytes(input).length); + } + + /** + * @dev Variant of {parseAddress-string} that parses a substring of `input` located between position `begin` (included) and + * `end` (excluded). + * + * Requirements: + * - The substring must be formatted as `(0x)?[0-9a-fA-F]{40}` + */ + function parseAddress(string memory input, uint256 begin, uint256 end) internal pure returns (address) { + (bool success, address value) = tryParseAddress(input, begin, end); + if (!success) revert StringsInvalidAddressFormat(); + return value; + } + + /** + * @dev Variant of {parseAddress-string} that returns false if the parsing fails because the input is not a properly + * formatted address. See {parseAddress-string} requirements. + */ + function tryParseAddress(string memory input) internal pure returns (bool success, address value) { + return tryParseAddress(input, 0, bytes(input).length); + } + + /** + * @dev Variant of {parseAddress-string-uint256-uint256} that returns false if the parsing fails because input is not a properly + * formatted address. See {parseAddress-string-uint256-uint256} requirements. + */ + function tryParseAddress( + string memory input, + uint256 begin, + uint256 end + ) internal pure returns (bool success, address value) { + if (end > bytes(input).length || begin > end) return (false, address(0)); + + bool hasPrefix = (end > begin + 1) && bytes2(_unsafeReadBytesOffset(bytes(input), begin)) == bytes2("0x"); // don't do out-of-bound (possibly unsafe) read if sub-string is empty + uint256 expectedLength = 40 + hasPrefix.toUint() * 2; + + // check that input is the correct length + if (end - begin == expectedLength) { + // length guarantees that this does not overflow, and value is at most type(uint160).max + (bool s, uint256 v) = _tryParseHexUintUncheckedBounds(input, begin, end); + return (s, address(uint160(v))); + } else { + return (false, address(0)); + } + } + + function _tryParseChr(bytes1 chr) private pure returns (uint8) { + uint8 value = uint8(chr); + + // Try to parse `chr`: + // - Case 1: [0-9] + // - Case 2: [a-f] + // - Case 3: [A-F] + // - otherwise not supported + unchecked { + if (value > 47 && value < 58) value -= 48; + else if (value > 96 && value < 103) value -= 87; + else if (value > 64 && value < 71) value -= 55; + else return type(uint8).max; + } + + return value; + } + + /** + * @dev Escape special characters in JSON strings. This can be useful to prevent JSON injection in NFT metadata. + * + * WARNING: This function should only be used in double quoted JSON strings. Single quotes are not escaped. + * + * NOTE: This function escapes all unicode characters, and not just the ones in ranges defined in section 2.5 of + * RFC-4627 (U+0000 to U+001F, U+0022 and U+005C). ECMAScript's `JSON.parse` does recover escaped unicode + * characters that are not in this range, but other tooling may provide different results. + */ + function escapeJSON(string memory input) internal pure returns (string memory) { + bytes memory buffer = bytes(input); + bytes memory output = new bytes(2 * buffer.length); // worst case scenario + uint256 outputLength = 0; + + for (uint256 i; i < buffer.length; ++i) { + bytes1 char = bytes1(_unsafeReadBytesOffset(buffer, i)); + if (((SPECIAL_CHARS_LOOKUP & (1 << uint8(char))) != 0)) { + output[outputLength++] = "\\"; + if (char == 0x08) output[outputLength++] = "b"; + else if (char == 0x09) output[outputLength++] = "t"; + else if (char == 0x0a) output[outputLength++] = "n"; + else if (char == 0x0c) output[outputLength++] = "f"; + else if (char == 0x0d) output[outputLength++] = "r"; + else if (char == 0x5c) output[outputLength++] = "\\"; + else if (char == 0x22) { + // solhint-disable-next-line quotes + output[outputLength++] = '"'; + } + } else { + output[outputLength++] = char; + } + } + // write the actual length and deallocate unused memory + assembly ("memory-safe") { + mstore(output, outputLength) + mstore(0x40, add(output, shl(5, shr(5, add(outputLength, 63))))) + } + + return string(output); + } + + /** + * @dev Reads a bytes32 from a bytes array without bounds checking. + * + * NOTE: making this function internal would mean it could be used with memory unsafe offset, and marking the + * assembly block as such would prevent some optimizations. + */ + function _unsafeReadBytesOffset(bytes memory buffer, uint256 offset) private pure returns (bytes32 value) { + // This is not memory safe in the general case, but all calls to this private function are within bounds. + assembly ("memory-safe") { + value := mload(add(add(buffer, 0x20), offset)) + } + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/utils/TransientSlot.sol b/dependencies/@openzeppelin-contracts-5.4.0/utils/TransientSlot.sol new file mode 100644 index 00000000..f0caea13 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/utils/TransientSlot.sol @@ -0,0 +1,183 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.3.0) (utils/TransientSlot.sol) +// This file was procedurally generated from scripts/generate/templates/TransientSlot.js. + +pragma solidity ^0.8.24; + +/** + * @dev Library for reading and writing value-types to specific transient storage slots. + * + * Transient slots are often used to store temporary values that are removed after the current transaction. + * This library helps with reading and writing to such slots without the need for inline assembly. + * + * * Example reading and writing values using transient storage: + * ```solidity + * contract Lock { + * using TransientSlot for *; + * + * // Define the slot. Alternatively, use the SlotDerivation library to derive the slot. + * bytes32 internal constant _LOCK_SLOT = 0xf4678858b2b588224636b8522b729e7722d32fc491da849ed75b3fdf3c84f542; + * + * modifier locked() { + * require(!_LOCK_SLOT.asBoolean().tload()); + * + * _LOCK_SLOT.asBoolean().tstore(true); + * _; + * _LOCK_SLOT.asBoolean().tstore(false); + * } + * } + * ``` + * + * TIP: Consider using this library along with {SlotDerivation}. + */ +library TransientSlot { + /** + * @dev UDVT that represents a slot holding an address. + */ + type AddressSlot is bytes32; + + /** + * @dev Cast an arbitrary slot to a AddressSlot. + */ + function asAddress(bytes32 slot) internal pure returns (AddressSlot) { + return AddressSlot.wrap(slot); + } + + /** + * @dev UDVT that represents a slot holding a bool. + */ + type BooleanSlot is bytes32; + + /** + * @dev Cast an arbitrary slot to a BooleanSlot. + */ + function asBoolean(bytes32 slot) internal pure returns (BooleanSlot) { + return BooleanSlot.wrap(slot); + } + + /** + * @dev UDVT that represents a slot holding a bytes32. + */ + type Bytes32Slot is bytes32; + + /** + * @dev Cast an arbitrary slot to a Bytes32Slot. + */ + function asBytes32(bytes32 slot) internal pure returns (Bytes32Slot) { + return Bytes32Slot.wrap(slot); + } + + /** + * @dev UDVT that represents a slot holding a uint256. + */ + type Uint256Slot is bytes32; + + /** + * @dev Cast an arbitrary slot to a Uint256Slot. + */ + function asUint256(bytes32 slot) internal pure returns (Uint256Slot) { + return Uint256Slot.wrap(slot); + } + + /** + * @dev UDVT that represents a slot holding a int256. + */ + type Int256Slot is bytes32; + + /** + * @dev Cast an arbitrary slot to a Int256Slot. + */ + function asInt256(bytes32 slot) internal pure returns (Int256Slot) { + return Int256Slot.wrap(slot); + } + + /** + * @dev Load the value held at location `slot` in transient storage. + */ + function tload(AddressSlot slot) internal view returns (address value) { + assembly ("memory-safe") { + value := tload(slot) + } + } + + /** + * @dev Store `value` at location `slot` in transient storage. + */ + function tstore(AddressSlot slot, address value) internal { + assembly ("memory-safe") { + tstore(slot, value) + } + } + + /** + * @dev Load the value held at location `slot` in transient storage. + */ + function tload(BooleanSlot slot) internal view returns (bool value) { + assembly ("memory-safe") { + value := tload(slot) + } + } + + /** + * @dev Store `value` at location `slot` in transient storage. + */ + function tstore(BooleanSlot slot, bool value) internal { + assembly ("memory-safe") { + tstore(slot, value) + } + } + + /** + * @dev Load the value held at location `slot` in transient storage. + */ + function tload(Bytes32Slot slot) internal view returns (bytes32 value) { + assembly ("memory-safe") { + value := tload(slot) + } + } + + /** + * @dev Store `value` at location `slot` in transient storage. + */ + function tstore(Bytes32Slot slot, bytes32 value) internal { + assembly ("memory-safe") { + tstore(slot, value) + } + } + + /** + * @dev Load the value held at location `slot` in transient storage. + */ + function tload(Uint256Slot slot) internal view returns (uint256 value) { + assembly ("memory-safe") { + value := tload(slot) + } + } + + /** + * @dev Store `value` at location `slot` in transient storage. + */ + function tstore(Uint256Slot slot, uint256 value) internal { + assembly ("memory-safe") { + tstore(slot, value) + } + } + + /** + * @dev Load the value held at location `slot` in transient storage. + */ + function tload(Int256Slot slot) internal view returns (int256 value) { + assembly ("memory-safe") { + value := tload(slot) + } + } + + /** + * @dev Store `value` at location `slot` in transient storage. + */ + function tstore(Int256Slot slot, int256 value) internal { + assembly ("memory-safe") { + tstore(slot, value) + } + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/ECDSA.sol b/dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/ECDSA.sol new file mode 100644 index 00000000..6493f563 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/ECDSA.sol @@ -0,0 +1,180 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.1.0) (utils/cryptography/ECDSA.sol) + +pragma solidity ^0.8.20; + +/** + * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. + * + * These functions can be used to verify that a message was signed by the holder + * of the private keys of a given address. + */ +library ECDSA { + enum RecoverError { + NoError, + InvalidSignature, + InvalidSignatureLength, + InvalidSignatureS + } + + /** + * @dev The signature derives the `address(0)`. + */ + error ECDSAInvalidSignature(); + + /** + * @dev The signature has an invalid length. + */ + error ECDSAInvalidSignatureLength(uint256 length); + + /** + * @dev The signature has an S value that is in the upper half order. + */ + error ECDSAInvalidSignatureS(bytes32 s); + + /** + * @dev Returns the address that signed a hashed message (`hash`) with `signature` or an error. This will not + * return address(0) without also returning an error description. Errors are documented using an enum (error type) + * and a bytes32 providing additional information about the error. + * + * If no error is returned, then the address can be used for verification purposes. + * + * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures: + * this function rejects them by requiring the `s` value to be in the lower + * half order, and the `v` value to be either 27 or 28. + * + * IMPORTANT: `hash` _must_ be the result of a hash operation for the + * verification to be secure: it is possible to craft signatures that + * recover to arbitrary addresses for non-hashed data. A safe way to ensure + * this is by receiving a hash of the original message (which may otherwise + * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it. + * + * Documentation for signature generation: + * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] + * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] + */ + function tryRecover( + bytes32 hash, + bytes memory signature + ) internal pure returns (address recovered, RecoverError err, bytes32 errArg) { + if (signature.length == 65) { + bytes32 r; + bytes32 s; + uint8 v; + // ecrecover takes the signature parameters, and the only way to get them + // currently is to use assembly. + assembly ("memory-safe") { + r := mload(add(signature, 0x20)) + s := mload(add(signature, 0x40)) + v := byte(0, mload(add(signature, 0x60))) + } + return tryRecover(hash, v, r, s); + } else { + return (address(0), RecoverError.InvalidSignatureLength, bytes32(signature.length)); + } + } + + /** + * @dev Returns the address that signed a hashed message (`hash`) with + * `signature`. This address can then be used for verification purposes. + * + * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures: + * this function rejects them by requiring the `s` value to be in the lower + * half order, and the `v` value to be either 27 or 28. + * + * IMPORTANT: `hash` _must_ be the result of a hash operation for the + * verification to be secure: it is possible to craft signatures that + * recover to arbitrary addresses for non-hashed data. A safe way to ensure + * this is by receiving a hash of the original message (which may otherwise + * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it. + */ + function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { + (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, signature); + _throwError(error, errorArg); + return recovered; + } + + /** + * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. + * + * See https://eips.ethereum.org/EIPS/eip-2098[ERC-2098 short signatures] + */ + function tryRecover( + bytes32 hash, + bytes32 r, + bytes32 vs + ) internal pure returns (address recovered, RecoverError err, bytes32 errArg) { + unchecked { + bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); + // We do not check for an overflow here since the shift operation results in 0 or 1. + uint8 v = uint8((uint256(vs) >> 255) + 27); + return tryRecover(hash, v, r, s); + } + } + + /** + * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. + */ + function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) { + (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, r, vs); + _throwError(error, errorArg); + return recovered; + } + + /** + * @dev Overload of {ECDSA-tryRecover} that receives the `v`, + * `r` and `s` signature fields separately. + */ + function tryRecover( + bytes32 hash, + uint8 v, + bytes32 r, + bytes32 s + ) internal pure returns (address recovered, RecoverError err, bytes32 errArg) { + // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature + // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines + // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most + // signatures from current libraries generate a unique signature with an s-value in the lower half order. + // + // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value + // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or + // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept + // these malleable signatures as well. + if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { + return (address(0), RecoverError.InvalidSignatureS, s); + } + + // If the signature is valid (and not malleable), return the signer address + address signer = ecrecover(hash, v, r, s); + if (signer == address(0)) { + return (address(0), RecoverError.InvalidSignature, bytes32(0)); + } + + return (signer, RecoverError.NoError, bytes32(0)); + } + + /** + * @dev Overload of {ECDSA-recover} that receives the `v`, + * `r` and `s` signature fields separately. + */ + function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) { + (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, v, r, s); + _throwError(error, errorArg); + return recovered; + } + + /** + * @dev Optionally reverts with the corresponding custom error according to the `error` argument provided. + */ + function _throwError(RecoverError error, bytes32 errorArg) private pure { + if (error == RecoverError.NoError) { + return; // no error: do nothing + } else if (error == RecoverError.InvalidSignature) { + revert ECDSAInvalidSignature(); + } else if (error == RecoverError.InvalidSignatureLength) { + revert ECDSAInvalidSignatureLength(uint256(errorArg)); + } else if (error == RecoverError.InvalidSignatureS) { + revert ECDSAInvalidSignatureS(errorArg); + } + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/EIP712.sol b/dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/EIP712.sol new file mode 100644 index 00000000..6400cbca --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/EIP712.sol @@ -0,0 +1,160 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (utils/cryptography/EIP712.sol) + +pragma solidity ^0.8.20; + +import {MessageHashUtils} from "./MessageHashUtils.sol"; +import {ShortStrings, ShortString} from "../ShortStrings.sol"; +import {IERC5267} from "../../interfaces/IERC5267.sol"; + +/** + * @dev https://eips.ethereum.org/EIPS/eip-712[EIP-712] is a standard for hashing and signing of typed structured data. + * + * The encoding scheme specified in the EIP requires a domain separator and a hash of the typed structured data, whose + * encoding is very generic and therefore its implementation in Solidity is not feasible, thus this contract + * does not implement the encoding itself. Protocols need to implement the type-specific encoding they need in order to + * produce the hash of their typed data using a combination of `abi.encode` and `keccak256`. + * + * This contract implements the EIP-712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding + * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA + * ({_hashTypedDataV4}). + * + * The implementation of the domain separator was designed to be as efficient as possible while still properly updating + * the chain id to protect against replay attacks on an eventual fork of the chain. + * + * NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method + * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask]. + * + * 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. + * + * @custom:oz-upgrades-unsafe-allow state-variable-immutable + */ +abstract contract EIP712 is IERC5267 { + using ShortStrings for *; + + bytes32 private constant TYPE_HASH = + keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"); + + // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to + // invalidate the cached domain separator if the chain id changes. + bytes32 private immutable _cachedDomainSeparator; + uint256 private immutable _cachedChainId; + address private immutable _cachedThis; + + bytes32 private immutable _hashedName; + bytes32 private immutable _hashedVersion; + + 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; + + /** + * @dev Initializes the domain separator and parameter caches. + * + * The meaning of `name` and `version` is specified in + * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP-712]: + * + * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol. + * - `version`: the current major version of the signing domain. + * + * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart + * contract upgrade]. + */ + constructor(string memory name, string memory version) { + _name = name.toShortStringWithFallback(_nameFallback); + _version = version.toShortStringWithFallback(_versionFallback); + _hashedName = keccak256(bytes(name)); + _hashedVersion = keccak256(bytes(version)); + + _cachedChainId = block.chainid; + _cachedDomainSeparator = _buildDomainSeparator(); + _cachedThis = address(this); + } + + /** + * @dev Returns the domain separator for the current chain. + */ + function _domainSeparatorV4() internal view returns (bytes32) { + if (address(this) == _cachedThis && block.chainid == _cachedChainId) { + return _cachedDomainSeparator; + } else { + return _buildDomainSeparator(); + } + } + + function _buildDomainSeparator() private view returns (bytes32) { + return keccak256(abi.encode(TYPE_HASH, _hashedName, _hashedVersion, block.chainid, address(this))); + } + + /** + * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this + * function returns the hash of the fully encoded EIP712 message for this domain. + * + * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example: + * + * ```solidity + * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode( + * keccak256("Mail(address to,string contents)"), + * mailTo, + * keccak256(bytes(mailContents)) + * ))); + * address signer = ECDSA.recover(digest, signature); + * ``` + */ + function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) { + return MessageHashUtils.toTypedDataHash(_domainSeparatorV4(), structHash); + } + + /// @inheritdoc IERC5267 + function eip712Domain() + public + view + virtual + returns ( + bytes1 fields, + string memory name, + string memory version, + uint256 chainId, + address verifyingContract, + bytes32 salt, + uint256[] memory extensions + ) + { + return ( + hex"0f", // 01111 + _EIP712Name(), + _EIP712Version(), + block.chainid, + address(this), + bytes32(0), + new uint256[](0) + ); + } + + /** + * @dev The name parameter for the EIP712 domain. + * + * NOTE: By default this function reads _name which is an immutable value. + * It only reads from storage if necessary (in case the value is too large to fit in a ShortString). + */ + // solhint-disable-next-line func-name-mixedcase + function _EIP712Name() internal view returns (string memory) { + return _name.toStringWithFallback(_nameFallback); + } + + /** + * @dev The version parameter for the EIP712 domain. + * + * NOTE: By default this function reads _version which is an immutable value. + * It only reads from storage if necessary (in case the value is too large to fit in a ShortString). + */ + // solhint-disable-next-line func-name-mixedcase + function _EIP712Version() internal view returns (string memory) { + return _version.toStringWithFallback(_versionFallback); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/Hashes.sol b/dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/Hashes.sol new file mode 100644 index 00000000..48c9bbe2 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/Hashes.sol @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.3.0) (utils/cryptography/Hashes.sol) + +pragma solidity ^0.8.20; + +/** + * @dev Library of standard hash functions. + * + * _Available since v5.1._ + */ +library Hashes { + /** + * @dev Commutative Keccak256 hash of a sorted pair of bytes32. Frequently used when working with merkle proofs. + * + * NOTE: Equivalent to the `standardNodeHash` in our https://github.com/OpenZeppelin/merkle-tree[JavaScript library]. + */ + function commutativeKeccak256(bytes32 a, bytes32 b) internal pure returns (bytes32) { + return a < b ? efficientKeccak256(a, b) : efficientKeccak256(b, a); + } + + /** + * @dev Implementation of keccak256(abi.encode(a, b)) that doesn't allocate or expand memory. + */ + function efficientKeccak256(bytes32 a, bytes32 b) internal pure returns (bytes32 value) { + assembly ("memory-safe") { + mstore(0x00, a) + mstore(0x20, b) + value := keccak256(0x00, 0x40) + } + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/MerkleProof.sol b/dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/MerkleProof.sol new file mode 100644 index 00000000..19b09e2a --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/MerkleProof.sol @@ -0,0 +1,514 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.1.0) (utils/cryptography/MerkleProof.sol) +// This file was procedurally generated from scripts/generate/templates/MerkleProof.js. + +pragma solidity ^0.8.20; + +import {Hashes} from "./Hashes.sol"; + +/** + * @dev These functions deal with verification of Merkle Tree proofs. + * + * The tree and the proofs can be generated using our + * https://github.com/OpenZeppelin/merkle-tree[JavaScript library]. + * You will find a quickstart guide in the readme. + * + * WARNING: You should avoid using leaf values that are 64 bytes long prior to + * hashing, or use a hash function other than keccak256 for hashing leaves. + * This is because the concatenation of a sorted pair of internal nodes in + * the Merkle tree could be reinterpreted as a leaf value. + * OpenZeppelin's JavaScript library generates Merkle trees that are safe + * against this attack out of the box. + * + * IMPORTANT: Consider memory side-effects when using custom hashing functions + * that access memory in an unsafe way. + * + * NOTE: This library supports proof verification for merkle trees built using + * custom _commutative_ hashing functions (i.e. `H(a, b) == H(b, a)`). Proving + * leaf inclusion in trees built using non-commutative hashing functions requires + * additional logic that is not supported by this library. + */ +library MerkleProof { + /** + *@dev The multiproof provided is not valid. + */ + error MerkleProofInvalidMultiproof(); + + /** + * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree + * defined by `root`. For this, a `proof` must be provided, containing + * sibling hashes on the branch from the leaf to the root of the tree. Each + * pair of leaves and each pair of pre-images are assumed to be sorted. + * + * This version handles proofs in memory with the default hashing function. + */ + function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) { + return processProof(proof, leaf) == root; + } + + /** + * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up + * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt + * hash matches the root of the tree. When processing the proof, the pairs + * of leaves & pre-images are assumed to be sorted. + * + * This version handles proofs in memory with the default hashing function. + */ + function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) { + bytes32 computedHash = leaf; + for (uint256 i = 0; i < proof.length; i++) { + computedHash = Hashes.commutativeKeccak256(computedHash, proof[i]); + } + return computedHash; + } + + /** + * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree + * defined by `root`. For this, a `proof` must be provided, containing + * sibling hashes on the branch from the leaf to the root of the tree. Each + * pair of leaves and each pair of pre-images are assumed to be sorted. + * + * This version handles proofs in memory with a custom hashing function. + */ + function verify( + bytes32[] memory proof, + bytes32 root, + bytes32 leaf, + function(bytes32, bytes32) view returns (bytes32) hasher + ) internal view returns (bool) { + return processProof(proof, leaf, hasher) == root; + } + + /** + * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up + * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt + * hash matches the root of the tree. When processing the proof, the pairs + * of leaves & pre-images are assumed to be sorted. + * + * This version handles proofs in memory with a custom hashing function. + */ + function processProof( + bytes32[] memory proof, + bytes32 leaf, + function(bytes32, bytes32) view returns (bytes32) hasher + ) internal view returns (bytes32) { + bytes32 computedHash = leaf; + for (uint256 i = 0; i < proof.length; i++) { + computedHash = hasher(computedHash, proof[i]); + } + return computedHash; + } + + /** + * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree + * defined by `root`. For this, a `proof` must be provided, containing + * sibling hashes on the branch from the leaf to the root of the tree. Each + * pair of leaves and each pair of pre-images are assumed to be sorted. + * + * This version handles proofs in calldata with the default hashing function. + */ + function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) { + return processProofCalldata(proof, leaf) == root; + } + + /** + * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up + * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt + * hash matches the root of the tree. When processing the proof, the pairs + * of leaves & pre-images are assumed to be sorted. + * + * This version handles proofs in calldata with the default hashing function. + */ + function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) { + bytes32 computedHash = leaf; + for (uint256 i = 0; i < proof.length; i++) { + computedHash = Hashes.commutativeKeccak256(computedHash, proof[i]); + } + return computedHash; + } + + /** + * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree + * defined by `root`. For this, a `proof` must be provided, containing + * sibling hashes on the branch from the leaf to the root of the tree. Each + * pair of leaves and each pair of pre-images are assumed to be sorted. + * + * This version handles proofs in calldata with a custom hashing function. + */ + function verifyCalldata( + bytes32[] calldata proof, + bytes32 root, + bytes32 leaf, + function(bytes32, bytes32) view returns (bytes32) hasher + ) internal view returns (bool) { + return processProofCalldata(proof, leaf, hasher) == root; + } + + /** + * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up + * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt + * hash matches the root of the tree. When processing the proof, the pairs + * of leaves & pre-images are assumed to be sorted. + * + * This version handles proofs in calldata with a custom hashing function. + */ + function processProofCalldata( + bytes32[] calldata proof, + bytes32 leaf, + function(bytes32, bytes32) view returns (bytes32) hasher + ) internal view returns (bytes32) { + bytes32 computedHash = leaf; + for (uint256 i = 0; i < proof.length; i++) { + computedHash = hasher(computedHash, proof[i]); + } + return computedHash; + } + + /** + * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a Merkle tree defined by + * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}. + * + * This version handles multiproofs in memory with the default hashing function. + * + * CAUTION: Not all Merkle trees admit multiproofs. See {processMultiProof} for details. + * + * NOTE: Consider the case where `root == proof[0] && leaves.length == 0` as it will return `true`. + * The `leaves` must be validated independently. See {processMultiProof}. + */ + function multiProofVerify( + bytes32[] memory proof, + bool[] memory proofFlags, + bytes32 root, + bytes32[] memory leaves + ) internal pure returns (bool) { + return processMultiProof(proof, proofFlags, leaves) == root; + } + + /** + * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction + * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another + * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false + * respectively. + * + * This version handles multiproofs in memory with the default hashing function. + * + * CAUTION: Not all Merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree + * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the + * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer). + * + * NOTE: The _empty set_ (i.e. the case where `proof.length == 1 && leaves.length == 0`) is considered a no-op, + * and therefore a valid multiproof (i.e. it returns `proof[0]`). Consider disallowing this case if you're not + * validating the leaves elsewhere. + */ + function processMultiProof( + bytes32[] memory proof, + bool[] memory proofFlags, + bytes32[] memory leaves + ) internal pure returns (bytes32 merkleRoot) { + // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by + // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the + // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of + // the Merkle tree. + uint256 leavesLen = leaves.length; + uint256 proofFlagsLen = proofFlags.length; + + // Check proof validity. + if (leavesLen + proof.length != proofFlagsLen + 1) { + revert MerkleProofInvalidMultiproof(); + } + + // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using + // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop". + bytes32[] memory hashes = new bytes32[](proofFlagsLen); + uint256 leafPos = 0; + uint256 hashPos = 0; + uint256 proofPos = 0; + // At each step, we compute the next hash using two values: + // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we + // get the next hash. + // - depending on the flag, either another value from the "main queue" (merging branches) or an element from the + // `proof` array. + for (uint256 i = 0; i < proofFlagsLen; i++) { + bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]; + bytes32 b = proofFlags[i] + ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]) + : proof[proofPos++]; + hashes[i] = Hashes.commutativeKeccak256(a, b); + } + + if (proofFlagsLen > 0) { + if (proofPos != proof.length) { + revert MerkleProofInvalidMultiproof(); + } + unchecked { + return hashes[proofFlagsLen - 1]; + } + } else if (leavesLen > 0) { + return leaves[0]; + } else { + return proof[0]; + } + } + + /** + * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a Merkle tree defined by + * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}. + * + * This version handles multiproofs in memory with a custom hashing function. + * + * CAUTION: Not all Merkle trees admit multiproofs. See {processMultiProof} for details. + * + * NOTE: Consider the case where `root == proof[0] && leaves.length == 0` as it will return `true`. + * The `leaves` must be validated independently. See {processMultiProof}. + */ + function multiProofVerify( + bytes32[] memory proof, + bool[] memory proofFlags, + bytes32 root, + bytes32[] memory leaves, + function(bytes32, bytes32) view returns (bytes32) hasher + ) internal view returns (bool) { + return processMultiProof(proof, proofFlags, leaves, hasher) == root; + } + + /** + * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction + * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another + * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false + * respectively. + * + * This version handles multiproofs in memory with a custom hashing function. + * + * CAUTION: Not all Merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree + * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the + * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer). + * + * NOTE: The _empty set_ (i.e. the case where `proof.length == 1 && leaves.length == 0`) is considered a no-op, + * and therefore a valid multiproof (i.e. it returns `proof[0]`). Consider disallowing this case if you're not + * validating the leaves elsewhere. + */ + function processMultiProof( + bytes32[] memory proof, + bool[] memory proofFlags, + bytes32[] memory leaves, + function(bytes32, bytes32) view returns (bytes32) hasher + ) internal view returns (bytes32 merkleRoot) { + // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by + // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the + // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of + // the Merkle tree. + uint256 leavesLen = leaves.length; + uint256 proofFlagsLen = proofFlags.length; + + // Check proof validity. + if (leavesLen + proof.length != proofFlagsLen + 1) { + revert MerkleProofInvalidMultiproof(); + } + + // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using + // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop". + bytes32[] memory hashes = new bytes32[](proofFlagsLen); + uint256 leafPos = 0; + uint256 hashPos = 0; + uint256 proofPos = 0; + // At each step, we compute the next hash using two values: + // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we + // get the next hash. + // - depending on the flag, either another value from the "main queue" (merging branches) or an element from the + // `proof` array. + for (uint256 i = 0; i < proofFlagsLen; i++) { + bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]; + bytes32 b = proofFlags[i] + ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]) + : proof[proofPos++]; + hashes[i] = hasher(a, b); + } + + if (proofFlagsLen > 0) { + if (proofPos != proof.length) { + revert MerkleProofInvalidMultiproof(); + } + unchecked { + return hashes[proofFlagsLen - 1]; + } + } else if (leavesLen > 0) { + return leaves[0]; + } else { + return proof[0]; + } + } + + /** + * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a Merkle tree defined by + * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}. + * + * This version handles multiproofs in calldata with the default hashing function. + * + * CAUTION: Not all Merkle trees admit multiproofs. See {processMultiProof} for details. + * + * NOTE: Consider the case where `root == proof[0] && leaves.length == 0` as it will return `true`. + * The `leaves` must be validated independently. See {processMultiProofCalldata}. + */ + function multiProofVerifyCalldata( + bytes32[] calldata proof, + bool[] calldata proofFlags, + bytes32 root, + bytes32[] memory leaves + ) internal pure returns (bool) { + return processMultiProofCalldata(proof, proofFlags, leaves) == root; + } + + /** + * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction + * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another + * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false + * respectively. + * + * This version handles multiproofs in calldata with the default hashing function. + * + * CAUTION: Not all Merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree + * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the + * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer). + * + * NOTE: The _empty set_ (i.e. the case where `proof.length == 1 && leaves.length == 0`) is considered a no-op, + * and therefore a valid multiproof (i.e. it returns `proof[0]`). Consider disallowing this case if you're not + * validating the leaves elsewhere. + */ + function processMultiProofCalldata( + bytes32[] calldata proof, + bool[] calldata proofFlags, + bytes32[] memory leaves + ) internal pure returns (bytes32 merkleRoot) { + // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by + // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the + // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of + // the Merkle tree. + uint256 leavesLen = leaves.length; + uint256 proofFlagsLen = proofFlags.length; + + // Check proof validity. + if (leavesLen + proof.length != proofFlagsLen + 1) { + revert MerkleProofInvalidMultiproof(); + } + + // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using + // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop". + bytes32[] memory hashes = new bytes32[](proofFlagsLen); + uint256 leafPos = 0; + uint256 hashPos = 0; + uint256 proofPos = 0; + // At each step, we compute the next hash using two values: + // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we + // get the next hash. + // - depending on the flag, either another value from the "main queue" (merging branches) or an element from the + // `proof` array. + for (uint256 i = 0; i < proofFlagsLen; i++) { + bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]; + bytes32 b = proofFlags[i] + ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]) + : proof[proofPos++]; + hashes[i] = Hashes.commutativeKeccak256(a, b); + } + + if (proofFlagsLen > 0) { + if (proofPos != proof.length) { + revert MerkleProofInvalidMultiproof(); + } + unchecked { + return hashes[proofFlagsLen - 1]; + } + } else if (leavesLen > 0) { + return leaves[0]; + } else { + return proof[0]; + } + } + + /** + * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a Merkle tree defined by + * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}. + * + * This version handles multiproofs in calldata with a custom hashing function. + * + * CAUTION: Not all Merkle trees admit multiproofs. See {processMultiProof} for details. + * + * NOTE: Consider the case where `root == proof[0] && leaves.length == 0` as it will return `true`. + * The `leaves` must be validated independently. See {processMultiProofCalldata}. + */ + function multiProofVerifyCalldata( + bytes32[] calldata proof, + bool[] calldata proofFlags, + bytes32 root, + bytes32[] memory leaves, + function(bytes32, bytes32) view returns (bytes32) hasher + ) internal view returns (bool) { + return processMultiProofCalldata(proof, proofFlags, leaves, hasher) == root; + } + + /** + * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction + * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another + * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false + * respectively. + * + * This version handles multiproofs in calldata with a custom hashing function. + * + * CAUTION: Not all Merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree + * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the + * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer). + * + * NOTE: The _empty set_ (i.e. the case where `proof.length == 1 && leaves.length == 0`) is considered a no-op, + * and therefore a valid multiproof (i.e. it returns `proof[0]`). Consider disallowing this case if you're not + * validating the leaves elsewhere. + */ + function processMultiProofCalldata( + bytes32[] calldata proof, + bool[] calldata proofFlags, + bytes32[] memory leaves, + function(bytes32, bytes32) view returns (bytes32) hasher + ) internal view returns (bytes32 merkleRoot) { + // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by + // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the + // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of + // the Merkle tree. + uint256 leavesLen = leaves.length; + uint256 proofFlagsLen = proofFlags.length; + + // Check proof validity. + if (leavesLen + proof.length != proofFlagsLen + 1) { + revert MerkleProofInvalidMultiproof(); + } + + // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using + // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop". + bytes32[] memory hashes = new bytes32[](proofFlagsLen); + uint256 leafPos = 0; + uint256 hashPos = 0; + uint256 proofPos = 0; + // At each step, we compute the next hash using two values: + // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we + // get the next hash. + // - depending on the flag, either another value from the "main queue" (merging branches) or an element from the + // `proof` array. + for (uint256 i = 0; i < proofFlagsLen; i++) { + bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]; + bytes32 b = proofFlags[i] + ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]) + : proof[proofPos++]; + hashes[i] = hasher(a, b); + } + + if (proofFlagsLen > 0) { + if (proofPos != proof.length) { + revert MerkleProofInvalidMultiproof(); + } + unchecked { + return hashes[proofFlagsLen - 1]; + } + } else if (leavesLen > 0) { + return leaves[0]; + } else { + return proof[0]; + } + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/MessageHashUtils.sol b/dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/MessageHashUtils.sol new file mode 100644 index 00000000..37e92395 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/MessageHashUtils.sol @@ -0,0 +1,99 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.3.0) (utils/cryptography/MessageHashUtils.sol) + +pragma solidity ^0.8.20; + +import {Strings} from "../Strings.sol"; + +/** + * @dev Signature message hash utilities for producing digests to be consumed by {ECDSA} recovery or signing. + * + * The library provides methods for generating a hash of a message that conforms to the + * https://eips.ethereum.org/EIPS/eip-191[ERC-191] and https://eips.ethereum.org/EIPS/eip-712[EIP 712] + * specifications. + */ +library MessageHashUtils { + /** + * @dev Returns the keccak256 digest of an ERC-191 signed data with version + * `0x45` (`personal_sign` messages). + * + * The digest is calculated by prefixing a bytes32 `messageHash` with + * `"\x19Ethereum Signed Message:\n32"` and hashing the result. It corresponds with the + * hash signed when using the https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_sign[`eth_sign`] JSON-RPC method. + * + * NOTE: The `messageHash` parameter is intended to be the result of hashing a raw message with + * keccak256, although any bytes32 value can be safely used because the final digest will + * be re-hashed. + * + * See {ECDSA-recover}. + */ + function toEthSignedMessageHash(bytes32 messageHash) internal pure returns (bytes32 digest) { + assembly ("memory-safe") { + mstore(0x00, "\x19Ethereum Signed Message:\n32") // 32 is the bytes-length of messageHash + mstore(0x1c, messageHash) // 0x1c (28) is the length of the prefix + digest := keccak256(0x00, 0x3c) // 0x3c is the length of the prefix (0x1c) + messageHash (0x20) + } + } + + /** + * @dev Returns the keccak256 digest of an ERC-191 signed data with version + * `0x45` (`personal_sign` messages). + * + * The digest is calculated by prefixing an arbitrary `message` with + * `"\x19Ethereum Signed Message:\n" + len(message)` and hashing the result. It corresponds with the + * hash signed when using the https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_sign[`eth_sign`] JSON-RPC method. + * + * See {ECDSA-recover}. + */ + function toEthSignedMessageHash(bytes memory message) internal pure returns (bytes32) { + return + keccak256(bytes.concat("\x19Ethereum Signed Message:\n", bytes(Strings.toString(message.length)), message)); + } + + /** + * @dev Returns the keccak256 digest of an ERC-191 signed data with version + * `0x00` (data with intended validator). + * + * The digest is calculated by prefixing an arbitrary `data` with `"\x19\x00"` and the intended + * `validator` address. Then hashing the result. + * + * See {ECDSA-recover}. + */ + function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) { + return keccak256(abi.encodePacked(hex"19_00", validator, data)); + } + + /** + * @dev Variant of {toDataWithIntendedValidatorHash-address-bytes} optimized for cases where `data` is a bytes32. + */ + function toDataWithIntendedValidatorHash( + address validator, + bytes32 messageHash + ) internal pure returns (bytes32 digest) { + assembly ("memory-safe") { + mstore(0x00, hex"19_00") + mstore(0x02, shl(96, validator)) + mstore(0x16, messageHash) + digest := keccak256(0x00, 0x36) + } + } + + /** + * @dev Returns the keccak256 digest of an EIP-712 typed data (ERC-191 version `0x01`). + * + * The digest is calculated from a `domainSeparator` and a `structHash`, by prefixing them with + * `\x19\x01` and hashing the result. It corresponds to the hash signed by the + * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] JSON-RPC method as part of EIP-712. + * + * See {ECDSA-recover}. + */ + function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 digest) { + assembly ("memory-safe") { + let ptr := mload(0x40) + mstore(ptr, hex"19_01") + mstore(add(ptr, 0x02), domainSeparator) + mstore(add(ptr, 0x22), structHash) + digest := keccak256(ptr, 0x42) + } + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/P256.sol b/dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/P256.sol new file mode 100644 index 00000000..81d79adc --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/P256.sol @@ -0,0 +1,408 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.3.0) (utils/cryptography/P256.sol) +pragma solidity ^0.8.20; + +import {Math} from "../math/Math.sol"; +import {Errors} from "../Errors.sol"; + +/** + * @dev Implementation of secp256r1 verification and recovery functions. + * + * The secp256r1 curve (also known as P256) is a NIST standard curve with wide support in modern devices + * and cryptographic standards. Some notable examples include Apple's Secure Enclave and Android's Keystore + * as well as authentication protocols like FIDO2. + * + * Based on the original https://github.com/itsobvioustech/aa-passkeys-wallet/blob/d3d423f28a4d8dfcb203c7fa0c47f42592a7378e/src/Secp256r1.sol[implementation of itsobvioustech] (GNU General Public License v3.0). + * Heavily inspired in https://github.com/maxrobot/elliptic-solidity/blob/c4bb1b6e8ae89534d8db3a6b3a6b52219100520f/contracts/Secp256r1.sol[maxrobot] and + * https://github.com/tdrerup/elliptic-curve-solidity/blob/59a9c25957d4d190eff53b6610731d81a077a15e/contracts/curves/EllipticCurve.sol[tdrerup] implementations. + * + * _Available since v5.1._ + */ +library P256 { + struct JPoint { + uint256 x; + uint256 y; + uint256 z; + } + + /// @dev Generator (x component) + uint256 internal constant GX = 0x6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296; + /// @dev Generator (y component) + uint256 internal constant GY = 0x4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5; + /// @dev P (size of the field) + uint256 internal constant P = 0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF; + /// @dev N (order of G) + uint256 internal constant N = 0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551; + /// @dev A parameter of the weierstrass equation + uint256 internal constant A = 0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC; + /// @dev B parameter of the weierstrass equation + uint256 internal constant B = 0x5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B; + + /// @dev (P + 1) / 4. Useful to compute sqrt + uint256 private constant P1DIV4 = 0x3fffffffc0000000400000000000000000000000400000000000000000000000; + + /// @dev N/2 for excluding higher order `s` values + uint256 private constant HALF_N = 0x7fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a8; + + /** + * @dev Verifies a secp256r1 signature using the RIP-7212 precompile and falls back to the Solidity implementation + * if the precompile is not available. This version should work on all chains, but requires the deployment of more + * bytecode. + * + * @param h - hashed message + * @param r - signature half R + * @param s - signature half S + * @param qx - public key coordinate X + * @param qy - public key coordinate Y + * + * IMPORTANT: This function disallows signatures where the `s` value is above `N/2` to prevent malleability. + * To flip the `s` value, compute `s = N - s`. + */ + function verify(bytes32 h, bytes32 r, bytes32 s, bytes32 qx, bytes32 qy) internal view returns (bool) { + (bool valid, bool supported) = _tryVerifyNative(h, r, s, qx, qy); + return supported ? valid : verifySolidity(h, r, s, qx, qy); + } + + /** + * @dev Same as {verify}, but it will revert if the required precompile is not available. + * + * Make sure any logic (code or precompile) deployed at that address is the expected one, + * otherwise the returned value may be misinterpreted as a positive boolean. + */ + function verifyNative(bytes32 h, bytes32 r, bytes32 s, bytes32 qx, bytes32 qy) internal view returns (bool) { + (bool valid, bool supported) = _tryVerifyNative(h, r, s, qx, qy); + if (supported) { + return valid; + } else { + revert Errors.MissingPrecompile(address(0x100)); + } + } + + /** + * @dev Same as {verify}, but it will return false if the required precompile is not available. + */ + function _tryVerifyNative( + bytes32 h, + bytes32 r, + bytes32 s, + bytes32 qx, + bytes32 qy + ) private view returns (bool valid, bool supported) { + if (!_isProperSignature(r, s) || !isValidPublicKey(qx, qy)) { + return (false, true); // signature is invalid, and its not because the precompile is missing + } else if (_rip7212(h, r, s, qx, qy)) { + return (true, true); // precompile is present, signature is valid + } else if ( + // Given precompiles have no bytecode (i.e. `address(0x100).code.length == 0`), we use + // a valid signature with small `r` and `s` values to check if the precompile is present. Taken from + // https://github.com/C2SP/wycheproof/blob/4672ff74d68766e7785c2cac4c597effccef2c5c/testvectors/ecdsa_secp256r1_sha256_p1363_test.json#L1173-L1204 + _rip7212( + 0xbb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023, // sha256("123400") + 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000001, + 0xa71af64de5126a4a4e02b7922d66ce9415ce88a4c9d25514d91082c8725ac957, + 0x5d47723c8fbe580bb369fec9c2665d8e30a435b9932645482e7c9f11e872296b + ) + ) { + return (false, true); // precompile is present, signature is invalid + } else { + return (false, false); // precompile is absent + } + } + + /** + * @dev Low level helper for {_tryVerifyNative}. Calls the precompile and checks if there is a return value. + */ + function _rip7212(bytes32 h, bytes32 r, bytes32 s, bytes32 qx, bytes32 qy) private view returns (bool isValid) { + assembly ("memory-safe") { + // Use the free memory pointer without updating it at the end of the function + let ptr := mload(0x40) + mstore(ptr, h) + mstore(add(ptr, 0x20), r) + mstore(add(ptr, 0x40), s) + mstore(add(ptr, 0x60), qx) + mstore(add(ptr, 0x80), qy) + // RIP-7212 precompiles return empty bytes when an invalid signature is passed, making it impossible + // to distinguish the presence of the precompile. Custom precompile implementations may decide to + // return `bytes32(0)` (i.e. false) without developers noticing, so we decide to evaluate the return value + // without expanding memory using scratch space. + mstore(0x00, 0) // zero out scratch space in case the precompile doesn't return anything + if iszero(staticcall(gas(), 0x100, ptr, 0xa0, 0x00, 0x20)) { + invalid() + } + isValid := mload(0x00) + } + } + + /** + * @dev Same as {verify}, but only the Solidity implementation is used. + */ + function verifySolidity(bytes32 h, bytes32 r, bytes32 s, bytes32 qx, bytes32 qy) internal view returns (bool) { + if (!_isProperSignature(r, s) || !isValidPublicKey(qx, qy)) { + return false; + } + + JPoint[16] memory points = _preComputeJacobianPoints(uint256(qx), uint256(qy)); + uint256 w = Math.invModPrime(uint256(s), N); + uint256 u1 = mulmod(uint256(h), w, N); + uint256 u2 = mulmod(uint256(r), w, N); + (uint256 x, ) = _jMultShamir(points, u1, u2); + return ((x % N) == uint256(r)); + } + + /** + * @dev Public key recovery + * + * @param h - hashed message + * @param v - signature recovery param + * @param r - signature half R + * @param s - signature half S + * + * IMPORTANT: This function disallows signatures where the `s` value is above `N/2` to prevent malleability. + * To flip the `s` value, compute `s = N - s` and `v = 1 - v` if (`v = 0 | 1`). + */ + function recovery(bytes32 h, uint8 v, bytes32 r, bytes32 s) internal view returns (bytes32 x, bytes32 y) { + if (!_isProperSignature(r, s) || v > 1) { + return (0, 0); + } + + uint256 p = P; // cache P on the stack + uint256 rx = uint256(r); + uint256 ry2 = addmod(mulmod(addmod(mulmod(rx, rx, p), A, p), rx, p), B, p); // weierstrass equation y² = x³ + a.x + b + uint256 ry = Math.modExp(ry2, P1DIV4, p); // This formula for sqrt work because P ≡ 3 (mod 4) + if (mulmod(ry, ry, p) != ry2) return (0, 0); // Sanity check + if (ry % 2 != v) ry = p - ry; + + JPoint[16] memory points = _preComputeJacobianPoints(rx, ry); + uint256 w = Math.invModPrime(uint256(r), N); + uint256 u1 = mulmod(N - (uint256(h) % N), w, N); + uint256 u2 = mulmod(uint256(s), w, N); + (uint256 xU, uint256 yU) = _jMultShamir(points, u1, u2); + return (bytes32(xU), bytes32(yU)); + } + + /** + * @dev Checks if (x, y) are valid coordinates of a point on the curve. + * In particular this function checks that x < P and y < P. + */ + function isValidPublicKey(bytes32 x, bytes32 y) internal pure returns (bool result) { + assembly ("memory-safe") { + let p := P + let lhs := mulmod(y, y, p) // y^2 + let rhs := addmod(mulmod(addmod(mulmod(x, x, p), A, p), x, p), B, p) // ((x^2 + a) * x) + b = x^3 + ax + b + result := and(and(lt(x, p), lt(y, p)), eq(lhs, rhs)) // Should conform with the Weierstrass equation + } + } + + /** + * @dev Checks if (r, s) is a proper signature. + * In particular, this checks that `s` is in the "lower-range", making the signature non-malleable. + */ + function _isProperSignature(bytes32 r, bytes32 s) private pure returns (bool) { + return uint256(r) > 0 && uint256(r) < N && uint256(s) > 0 && uint256(s) <= HALF_N; + } + + /** + * @dev Reduce from jacobian to affine coordinates + * @param jx - jacobian coordinate x + * @param jy - jacobian coordinate y + * @param jz - jacobian coordinate z + * @return ax - affine coordinate x + * @return ay - affine coordinate y + */ + function _affineFromJacobian(uint256 jx, uint256 jy, uint256 jz) private view returns (uint256 ax, uint256 ay) { + if (jz == 0) return (0, 0); + uint256 p = P; // cache P on the stack + uint256 zinv = Math.invModPrime(jz, p); + assembly ("memory-safe") { + let zzinv := mulmod(zinv, zinv, p) + ax := mulmod(jx, zzinv, p) + ay := mulmod(jy, mulmod(zzinv, zinv, p), p) + } + } + + /** + * @dev Point addition on the jacobian coordinates + * Reference: https://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian.html#addition-add-1998-cmo-2 + * + * Note that: + * + * - `addition-add-1998-cmo-2` doesn't support identical input points. This version is modified to use + * the `h` and `r` values computed by `addition-add-1998-cmo-2` to detect identical inputs, and fallback to + * `doubling-dbl-1998-cmo-2` if needed. + * - if one of the points is at infinity (i.e. `z=0`), the result is undefined. + */ + function _jAdd( + JPoint memory p1, + uint256 x2, + uint256 y2, + uint256 z2 + ) private pure returns (uint256 rx, uint256 ry, uint256 rz) { + assembly ("memory-safe") { + let p := P + let z1 := mload(add(p1, 0x40)) + let zz1 := mulmod(z1, z1, p) // zz1 = z1² + let s1 := mulmod(mload(add(p1, 0x20)), mulmod(mulmod(z2, z2, p), z2, p), p) // s1 = y1*z2³ + let r := addmod(mulmod(y2, mulmod(zz1, z1, p), p), sub(p, s1), p) // r = s2-s1 = y2*z1³-s1 = y2*z1³-y1*z2³ + let u1 := mulmod(mload(p1), mulmod(z2, z2, p), p) // u1 = x1*z2² + let h := addmod(mulmod(x2, zz1, p), sub(p, u1), p) // h = u2-u1 = x2*z1²-u1 = x2*z1²-x1*z2² + + // detect edge cases where inputs are identical + switch and(iszero(r), iszero(h)) + // case 0: points are different + case 0 { + let hh := mulmod(h, h, p) // h² + + // x' = r²-h³-2*u1*h² + rx := addmod( + addmod(mulmod(r, r, p), sub(p, mulmod(h, hh, p)), p), + sub(p, mulmod(2, mulmod(u1, hh, p), p)), + p + ) + // y' = r*(u1*h²-x')-s1*h³ + ry := addmod( + mulmod(r, addmod(mulmod(u1, hh, p), sub(p, rx), p), p), + sub(p, mulmod(s1, mulmod(h, hh, p), p)), + p + ) + // z' = h*z1*z2 + rz := mulmod(h, mulmod(z1, z2, p), p) + } + // case 1: points are equal + case 1 { + let x := x2 + let y := y2 + let z := z2 + let yy := mulmod(y, y, p) + let zz := mulmod(z, z, p) + let m := addmod(mulmod(3, mulmod(x, x, p), p), mulmod(A, mulmod(zz, zz, p), p), p) // m = 3*x²+a*z⁴ + let s := mulmod(4, mulmod(x, yy, p), p) // s = 4*x*y² + + // x' = t = m²-2*s + rx := addmod(mulmod(m, m, p), sub(p, mulmod(2, s, p)), p) + + // y' = m*(s-t)-8*y⁴ = m*(s-x')-8*y⁴ + // cut the computation to avoid stack too deep + let rytmp1 := sub(p, mulmod(8, mulmod(yy, yy, p), p)) // -8*y⁴ + let rytmp2 := addmod(s, sub(p, rx), p) // s-x' + ry := addmod(mulmod(m, rytmp2, p), rytmp1, p) // m*(s-x')-8*y⁴ + + // z' = 2*y*z + rz := mulmod(2, mulmod(y, z, p), p) + } + } + } + + /** + * @dev Point doubling on the jacobian coordinates + * Reference: https://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian.html#doubling-dbl-1998-cmo-2 + */ + function _jDouble(uint256 x, uint256 y, uint256 z) private pure returns (uint256 rx, uint256 ry, uint256 rz) { + assembly ("memory-safe") { + let p := P + let yy := mulmod(y, y, p) + let zz := mulmod(z, z, p) + let m := addmod(mulmod(3, mulmod(x, x, p), p), mulmod(A, mulmod(zz, zz, p), p), p) // m = 3*x²+a*z⁴ + let s := mulmod(4, mulmod(x, yy, p), p) // s = 4*x*y² + + // x' = t = m²-2*s + rx := addmod(mulmod(m, m, p), sub(p, mulmod(2, s, p)), p) + // y' = m*(s-t)-8*y⁴ = m*(s-x')-8*y⁴ + ry := addmod(mulmod(m, addmod(s, sub(p, rx), p), p), sub(p, mulmod(8, mulmod(yy, yy, p), p)), p) + // z' = 2*y*z + rz := mulmod(2, mulmod(y, z, p), p) + } + } + + /** + * @dev Compute G·u1 + P·u2 using the precomputed points for G and P (see {_preComputeJacobianPoints}). + * + * Uses Strauss Shamir trick for EC multiplication + * https://stackoverflow.com/questions/50993471/ec-scalar-multiplication-with-strauss-shamir-method + * + * We optimize this for 2 bits at a time rather than a single bit. The individual points for a single pass are + * precomputed. Overall this reduces the number of additions while keeping the same number of + * doublings + */ + function _jMultShamir( + JPoint[16] memory points, + uint256 u1, + uint256 u2 + ) private view returns (uint256 rx, uint256 ry) { + uint256 x = 0; + uint256 y = 0; + uint256 z = 0; + unchecked { + for (uint256 i = 0; i < 128; ++i) { + if (z > 0) { + (x, y, z) = _jDouble(x, y, z); + (x, y, z) = _jDouble(x, y, z); + } + // Read 2 bits of u1, and 2 bits of u2. Combining the two gives the lookup index in the table. + uint256 pos = ((u1 >> 252) & 0xc) | ((u2 >> 254) & 0x3); + // Points that have z = 0 are points at infinity. They are the additive 0 of the group + // - if the lookup point is a 0, we can skip it + // - otherwise: + // - if the current point (x, y, z) is 0, we use the lookup point as our new value (0+P=P) + // - if the current point (x, y, z) is not 0, both points are valid and we can use `_jAdd` + if (points[pos].z != 0) { + if (z == 0) { + (x, y, z) = (points[pos].x, points[pos].y, points[pos].z); + } else { + (x, y, z) = _jAdd(points[pos], x, y, z); + } + } + u1 <<= 2; + u2 <<= 2; + } + } + return _affineFromJacobian(x, y, z); + } + + /** + * @dev Precompute a matrice of useful jacobian points associated with a given P. This can be seen as a 4x4 matrix + * that contains combination of P and G (generator) up to 3 times each. See the table below: + * + * ┌────┬─────────────────────┐ + * │ i │ 0 1 2 3 │ + * ├────┼─────────────────────┤ + * │ 0 │ 0 p 2p 3p │ + * │ 4 │ g g+p g+2p g+3p │ + * │ 8 │ 2g 2g+p 2g+2p 2g+3p │ + * │ 12 │ 3g 3g+p 3g+2p 3g+3p │ + * └────┴─────────────────────┘ + * + * Note that `_jAdd` (and thus `_jAddPoint`) does not handle the case where one of the inputs is a point at + * infinity (z = 0). However, we know that since `N ≡ 1 mod 2` and `N ≡ 1 mod 3`, there is no point P such that + * 2P = 0 or 3P = 0. This guarantees that g, 2g, 3g, p, 2p, 3p are all non-zero, and that all `_jAddPoint` calls + * have valid inputs. + */ + function _preComputeJacobianPoints(uint256 px, uint256 py) private pure returns (JPoint[16] memory points) { + points[0x00] = JPoint(0, 0, 0); // 0,0 + points[0x01] = JPoint(px, py, 1); // 1,0 (p) + points[0x04] = JPoint(GX, GY, 1); // 0,1 (g) + points[0x02] = _jDoublePoint(points[0x01]); // 2,0 (2p) + points[0x08] = _jDoublePoint(points[0x04]); // 0,2 (2g) + points[0x03] = _jAddPoint(points[0x01], points[0x02]); // 3,0 (p+2p = 3p) + points[0x05] = _jAddPoint(points[0x01], points[0x04]); // 1,1 (p+g) + points[0x06] = _jAddPoint(points[0x02], points[0x04]); // 2,1 (2p+g) + points[0x07] = _jAddPoint(points[0x03], points[0x04]); // 3,1 (3p+g) + points[0x09] = _jAddPoint(points[0x01], points[0x08]); // 1,2 (p+2g) + points[0x0a] = _jAddPoint(points[0x02], points[0x08]); // 2,2 (2p+2g) + points[0x0b] = _jAddPoint(points[0x03], points[0x08]); // 3,2 (3p+2g) + points[0x0c] = _jAddPoint(points[0x04], points[0x08]); // 0,3 (g+2g = 3g) + points[0x0d] = _jAddPoint(points[0x01], points[0x0c]); // 1,3 (p+3g) + points[0x0e] = _jAddPoint(points[0x02], points[0x0c]); // 2,3 (2p+3g) + points[0x0f] = _jAddPoint(points[0x03], points[0x0c]); // 3,3 (3p+3g) + } + + function _jAddPoint(JPoint memory p1, JPoint memory p2) private pure returns (JPoint memory) { + (uint256 x, uint256 y, uint256 z) = _jAdd(p1, p2.x, p2.y, p2.z); + return JPoint(x, y, z); + } + + function _jDoublePoint(JPoint memory p) private pure returns (JPoint memory) { + (uint256 x, uint256 y, uint256 z) = _jDouble(p.x, p.y, p.z); + return JPoint(x, y, z); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/RSA.sol b/dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/RSA.sol new file mode 100644 index 00000000..4e04ce5c --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/RSA.sol @@ -0,0 +1,154 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.1.0) (utils/cryptography/RSA.sol) +pragma solidity ^0.8.20; + +import {Math} from "../math/Math.sol"; + +/** + * @dev RSA PKCS#1 v1.5 signature verification implementation according to https://datatracker.ietf.org/doc/html/rfc8017[RFC8017]. + * + * This library supports PKCS#1 v1.5 padding to avoid malleability via chosen plaintext attacks in practical implementations. + * The padding follows the EMSA-PKCS1-v1_5-ENCODE encoding definition as per section 9.2 of the RFC. This padding makes + * RSA semantically secure for signing messages. + * + * Inspired by https://github.com/adria0/SolRsaVerify/blob/79c6182cabb9102ea69d4a2e996816091d5f1cd1[Adrià Massanet's work] (GNU General Public License v3.0). + * + * _Available since v5.1._ + */ +library RSA { + /** + * @dev Same as {pkcs1Sha256} but using SHA256 to calculate the digest of `data`. + */ + function pkcs1Sha256( + bytes memory data, + bytes memory s, + bytes memory e, + bytes memory n + ) internal view returns (bool) { + return pkcs1Sha256(sha256(data), s, e, n); + } + + /** + * @dev Verifies a PKCSv1.5 signature given a digest according to the verification + * method described in https://datatracker.ietf.org/doc/html/rfc8017#section-8.2.2[section 8.2.2 of RFC8017] with + * support for explicit or implicit NULL parameters in the DigestInfo (no other optional parameters are supported). + * + * IMPORTANT: For security reason, this function requires the signature and modulus to have a length of at least + * 2048 bits. If you use a smaller key, consider replacing it with a larger, more secure, one. + * + * WARNING: This verification algorithm doesn't prevent replayability. If called multiple times with the same + * digest, public key and (valid signature), it will return true every time. Consider including an onchain nonce + * or unique identifier in the message to prevent replay attacks. + * + * WARNING: This verification algorithm supports any exponent. NIST recommends using `65537` (or higher). + * That is the default value many libraries use, such as OpenSSL. Developers may choose to reject public keys + * using a low exponent out of security concerns. + * + * @param digest the digest to verify + * @param s is a buffer containing the signature + * @param e is the exponent of the public key + * @param n is the modulus of the public key + */ + function pkcs1Sha256(bytes32 digest, bytes memory s, bytes memory e, bytes memory n) internal view returns (bool) { + unchecked { + // cache and check length + uint256 length = n.length; + if ( + length < 0x100 || // Enforce 2048 bits minimum + length != s.length // signature must have the same length as the finite field + ) { + return false; + } + + // Verify that s < n to ensure there's only one valid signature for a given message + for (uint256 i = 0; i < length; i += 0x20) { + uint256 p = Math.min(i, length - 0x20); + bytes32 sp = _unsafeReadBytes32(s, p); + bytes32 np = _unsafeReadBytes32(n, p); + if (sp < np) { + // s < n in the upper bits (everything before is equal) → s < n globally: ok + break; + } else if (sp > np || p == length - 0x20) { + // s > n in the upper bits (everything before is equal) → s > n globally: fail + // or + // s = n and we are looking at the lower bits → s = n globally: fail + return false; + } + } + + // RSAVP1 https://datatracker.ietf.org/doc/html/rfc8017#section-5.2.2 + // The previous check guarantees that n > 0. Therefore modExp cannot revert. + bytes memory buffer = Math.modExp(s, e, n); + + // Check that buffer is well encoded: + // buffer ::= 0x00 | 0x01 | PS | 0x00 | DigestInfo + // + // With + // - PS is padding filled with 0xFF + // - DigestInfo ::= SEQUENCE { + // digestAlgorithm AlgorithmIdentifier, + // [optional algorithm parameters] -- not currently supported + // digest OCTET STRING + // } + + // Get AlgorithmIdentifier from the DigestInfo, and set the config accordingly + // - params: includes 00 + first part of DigestInfo + // - mask: filter to check the params + // - offset: length of the suffix (including digest) + bytes32 params; // 0x00 | DigestInfo + bytes32 mask; + uint256 offset; + + // Digest is expected at the end of the buffer. Therefore if NULL param is present, + // it should be at 32 (digest) + 2 bytes from the end. To those 34 bytes, we add the + // OID (9 bytes) and its length (2 bytes) to get the position of the DigestInfo sequence, + // which is expected to have a length of 0x31 when the NULL param is present or 0x2f if not. + if (bytes1(_unsafeReadBytes32(buffer, length - 0x32)) == 0x31) { + offset = 0x34; + // 00 (1 byte) | SEQUENCE length (0x31) = 3031 (2 bytes) | SEQUENCE length (0x0d) = 300d (2 bytes) | OBJECT_IDENTIFIER length (0x09) = 0609 (2 bytes) + // SHA256 OID = 608648016503040201 (9 bytes) | NULL = 0500 (2 bytes) (explicit) | OCTET_STRING length (0x20) = 0420 (2 bytes) + params = 0x003031300d060960864801650304020105000420000000000000000000000000; + mask = 0xffffffffffffffffffffffffffffffffffffffff000000000000000000000000; // (20 bytes) + } else if (bytes1(_unsafeReadBytes32(buffer, length - 0x30)) == 0x2F) { + offset = 0x32; + // 00 (1 byte) | SEQUENCE length (0x2f) = 302f (2 bytes) | SEQUENCE length (0x0b) = 300b (2 bytes) | OBJECT_IDENTIFIER length (0x09) = 0609 (2 bytes) + // SHA256 OID = 608648016503040201 (9 bytes) | NULL = | OCTET_STRING length (0x20) = 0420 (2 bytes) + params = 0x00302f300b060960864801650304020104200000000000000000000000000000; + mask = 0xffffffffffffffffffffffffffffffffffff0000000000000000000000000000; // (18 bytes) + } else { + // unknown + return false; + } + + // Length is at least 0x100 and offset is at most 0x34, so this is safe. There is always some padding. + uint256 paddingEnd = length - offset; + + // The padding has variable (arbitrary) length, so we check it byte per byte in a loop. + // This is required to ensure non-malleability. Not checking would allow an attacker to + // use the padding to manipulate the message in order to create a valid signature out of + // multiple valid signatures. + for (uint256 i = 2; i < paddingEnd; ++i) { + if (bytes1(_unsafeReadBytes32(buffer, i)) != 0xFF) { + return false; + } + } + + // All the other parameters are small enough to fit in a bytes32, so we can check them directly. + return + bytes2(0x0001) == bytes2(_unsafeReadBytes32(buffer, 0x00)) && // 00 | 01 + // PS was checked in the loop + params == _unsafeReadBytes32(buffer, paddingEnd) & mask && // DigestInfo + // Optional parameters are not checked + digest == _unsafeReadBytes32(buffer, length - 0x20); // Digest + } + } + + /// @dev Reads a bytes32 from a bytes array without bounds checking. + function _unsafeReadBytes32(bytes memory array, uint256 offset) private pure returns (bytes32 result) { + // Memory safeness is guaranteed as long as the provided `array` is a Solidity-allocated bytes array + // and `offset` is within bounds. This is the case for all calls to this private function from {pkcs1Sha256}. + assembly ("memory-safe") { + result := mload(add(add(array, 0x20), offset)) + } + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/SignatureChecker.sol b/dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/SignatureChecker.sol new file mode 100644 index 00000000..f85b24cb --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/SignatureChecker.sol @@ -0,0 +1,135 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (utils/cryptography/SignatureChecker.sol) + +pragma solidity ^0.8.24; + +import {ECDSA} from "./ECDSA.sol"; +import {IERC1271} from "../../interfaces/IERC1271.sol"; +import {IERC7913SignatureVerifier} from "../../interfaces/IERC7913.sol"; +import {Bytes} from "../../utils/Bytes.sol"; + +/** + * @dev Signature verification helper that can be used instead of `ECDSA.recover` to seamlessly support: + * + * * ECDSA signatures from externally owned accounts (EOAs) + * * ERC-1271 signatures from smart contract wallets like Argent and Safe Wallet (previously Gnosis Safe) + * * ERC-7913 signatures from keys that do not have an Ethereum address of their own + * + * See https://eips.ethereum.org/EIPS/eip-1271[ERC-1271] and https://eips.ethereum.org/EIPS/eip-7913[ERC-7913]. + */ +library SignatureChecker { + using Bytes for bytes; + + /** + * @dev Checks if a signature is valid for a given signer and data hash. If the signer has code, the + * signature is validated against it using ERC-1271, otherwise it's validated using `ECDSA.recover`. + * + * NOTE: Unlike ECDSA signatures, contract signatures are revocable, and the outcome of this function can thus + * change through time. It could return true at block N and false at block N+1 (or the opposite). + * + * NOTE: For an extended version of this function that supports ERC-7913 signatures, see {isValidSignatureNow-bytes-bytes32-bytes-}. + */ + function isValidSignatureNow(address signer, bytes32 hash, bytes memory signature) internal view returns (bool) { + if (signer.code.length == 0) { + (address recovered, ECDSA.RecoverError err, ) = ECDSA.tryRecover(hash, signature); + return err == ECDSA.RecoverError.NoError && recovered == signer; + } else { + return isValidERC1271SignatureNow(signer, hash, signature); + } + } + + /** + * @dev Checks if a signature is valid for a given signer and data hash. The signature is validated + * against the signer smart contract using ERC-1271. + * + * NOTE: Unlike ECDSA signatures, contract signatures are revocable, and the outcome of this function can thus + * change through time. It could return true at block N and false at block N+1 (or the opposite). + */ + function isValidERC1271SignatureNow( + address signer, + bytes32 hash, + bytes memory signature + ) internal view returns (bool) { + (bool success, bytes memory result) = signer.staticcall( + abi.encodeCall(IERC1271.isValidSignature, (hash, signature)) + ); + return (success && + result.length >= 32 && + abi.decode(result, (bytes32)) == bytes32(IERC1271.isValidSignature.selector)); + } + + /** + * @dev Verifies a signature for a given ERC-7913 signer and hash. + * + * The signer is a `bytes` object that is the concatenation of an address and optionally a key: + * `verifier || key`. A signer must be at least 20 bytes long. + * + * Verification is done as follows: + * + * * If `signer.length < 20`: verification fails + * * If `signer.length == 20`: verification is done using {isValidSignatureNow} + * * Otherwise: verification is done using {IERC7913SignatureVerifier} + * + * NOTE: Unlike ECDSA signatures, contract signatures are revocable, and the outcome of this function can thus + * change through time. It could return true at block N and false at block N+1 (or the opposite). + */ + function isValidSignatureNow( + bytes memory signer, + bytes32 hash, + bytes memory signature + ) internal view returns (bool) { + if (signer.length < 20) { + return false; + } else if (signer.length == 20) { + return isValidSignatureNow(address(bytes20(signer)), hash, signature); + } else { + (bool success, bytes memory result) = address(bytes20(signer)).staticcall( + abi.encodeCall(IERC7913SignatureVerifier.verify, (signer.slice(20), hash, signature)) + ); + return (success && + result.length >= 32 && + abi.decode(result, (bytes32)) == bytes32(IERC7913SignatureVerifier.verify.selector)); + } + } + + /** + * @dev Verifies multiple ERC-7913 `signatures` for a given `hash` using a set of `signers`. + * Returns `false` if the number of signers and signatures is not the same. + * + * The signers should be ordered by their `keccak256` hash to ensure efficient duplication check. Unordered + * signers are supported, but the uniqueness check will be more expensive. + * + * NOTE: Unlike ECDSA signatures, contract signatures are revocable, and the outcome of this function can thus + * change through time. It could return true at block N and false at block N+1 (or the opposite). + */ + function areValidSignaturesNow( + bytes32 hash, + bytes[] memory signers, + bytes[] memory signatures + ) internal view returns (bool) { + if (signers.length != signatures.length) return false; + + bytes32 lastId = bytes32(0); + + for (uint256 i = 0; i < signers.length; ++i) { + bytes memory signer = signers[i]; + + // If one of the signatures is invalid, reject the batch + if (!isValidSignatureNow(signer, hash, signatures[i])) return false; + + bytes32 id = keccak256(signer); + // If the current signer ID is greater than all previous IDs, then this is a new signer. + if (lastId < id) { + lastId = id; + } else { + // If this signer id is not greater than all the previous ones, verify that it is not a duplicate of a previous one + // This loop is never executed if the signers are ordered by id. + for (uint256 j = 0; j < i; ++j) { + if (id == keccak256(signers[j])) return false; + } + } + } + + return true; + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/draft-ERC7739Utils.sol b/dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/draft-ERC7739Utils.sol new file mode 100644 index 00000000..e47f20b4 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/draft-ERC7739Utils.sol @@ -0,0 +1,207 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (utils/cryptography/draft-ERC7739Utils.sol) + +pragma solidity ^0.8.20; + +import {Calldata} from "../Calldata.sol"; + +/** + * @dev Utilities to process https://ercs.ethereum.org/ERCS/erc-7739[ERC-7739] typed data signatures + * that are specific to an EIP-712 domain. + * + * This library provides methods to wrap, unwrap and operate over typed data signatures with a defensive + * rehashing mechanism that includes the app's xref:api:utils/cryptography#EIP712-_domainSeparatorV4[EIP-712] + * and preserves readability of the signed content using an EIP-712 nested approach. + * + * A smart contract domain can validate a signature for a typed data structure in two ways: + * + * - As an application validating a typed data signature. See {typedDataSignStructHash}. + * - As a smart contract validating a raw message signature. See {personalSignStructHash}. + * + * NOTE: A provider for a smart contract wallet would need to return this signature as the + * result of a call to `personal_sign` or `eth_signTypedData`, and this may be unsupported by + * API clients that expect a return value of 129 bytes, or specifically the `r,s,v` parameters + * of an xref:api:utils/cryptography#ECDSA[ECDSA] signature, as is for example specified for + * xref:api:utils/cryptography#EIP712[EIP-712]. + */ +library ERC7739Utils { + /** + * @dev An EIP-712 type to represent "personal" signatures + * (i.e. mimic of `personal_sign` for smart contracts). + */ + bytes32 private constant PERSONAL_SIGN_TYPEHASH = keccak256("PersonalSign(bytes prefixed)"); + + /** + * @dev Nest a signature for a given EIP-712 type into a nested signature for the domain of the app. + * + * Counterpart of {decodeTypedDataSig} to extract the original signature and the nested components. + */ + function encodeTypedDataSig( + bytes memory signature, + bytes32 appSeparator, + bytes32 contentsHash, + string memory contentsDescr + ) internal pure returns (bytes memory) { + return + abi.encodePacked(signature, appSeparator, contentsHash, contentsDescr, uint16(bytes(contentsDescr).length)); + } + + /** + * @dev Parses a nested signature into its components. + * + * Constructed as follows: + * + * `signature ‖ APP_DOMAIN_SEPARATOR ‖ contentsHash ‖ contentsDescr ‖ uint16(contentsDescr.length)` + * + * - `signature` is the signature for the (ERC-7739) nested struct hash. This signature indirectly signs over the + * original "contents" hash (from the app) and the account's domain separator. + * - `APP_DOMAIN_SEPARATOR` is the EIP-712 {EIP712-_domainSeparatorV4} of the application smart contract that is + * requesting the signature verification (though ERC-1271). + * - `contentsHash` is the hash of the underlying data structure or message. + * - `contentsDescr` is a descriptor of the "contents" part of the the EIP-712 type of the nested signature. + * + * NOTE: This function returns empty if the input format is invalid instead of reverting. + * data instead. + */ + function decodeTypedDataSig( + bytes calldata encodedSignature + ) + internal + pure + returns (bytes calldata signature, bytes32 appSeparator, bytes32 contentsHash, string calldata contentsDescr) + { + unchecked { + uint256 sigLength = encodedSignature.length; + + // 66 bytes = contentsDescrLength (2 bytes) + contentsHash (32 bytes) + APP_DOMAIN_SEPARATOR (32 bytes). + if (sigLength < 66) return (Calldata.emptyBytes(), 0, 0, Calldata.emptyString()); + + uint256 contentsDescrEnd = sigLength - 2; // Last 2 bytes + uint256 contentsDescrLength = uint16(bytes2(encodedSignature[contentsDescrEnd:])); + + // Check for space for `contentsDescr` in addition to the 66 bytes documented above + if (sigLength < 66 + contentsDescrLength) return (Calldata.emptyBytes(), 0, 0, Calldata.emptyString()); + + uint256 contentsHashEnd = contentsDescrEnd - contentsDescrLength; + uint256 separatorEnd = contentsHashEnd - 32; + uint256 signatureEnd = separatorEnd - 32; + + signature = encodedSignature[:signatureEnd]; + appSeparator = bytes32(encodedSignature[signatureEnd:separatorEnd]); + contentsHash = bytes32(encodedSignature[separatorEnd:contentsHashEnd]); + contentsDescr = string(encodedSignature[contentsHashEnd:contentsDescrEnd]); + } + } + + /** + * @dev Nests an `ERC-191` digest into a `PersonalSign` EIP-712 struct, and returns the corresponding struct hash. + * This struct hash must be combined with a domain separator, using {MessageHashUtils-toTypedDataHash} before + * being verified/recovered. + * + * This is used to simulates the `personal_sign` RPC method in the context of smart contracts. + */ + function personalSignStructHash(bytes32 contents) internal pure returns (bytes32) { + return keccak256(abi.encode(PERSONAL_SIGN_TYPEHASH, contents)); + } + + /** + * @dev Nests an `EIP-712` hash (`contents`) into a `TypedDataSign` EIP-712 struct, and returns the corresponding + * struct hash. This struct hash must be combined with a domain separator, using {MessageHashUtils-toTypedDataHash} + * before being verified/recovered. + */ + function typedDataSignStructHash( + string calldata contentsName, + string calldata contentsType, + bytes32 contentsHash, + bytes memory domainBytes + ) internal pure returns (bytes32 result) { + return + bytes(contentsName).length == 0 + ? bytes32(0) + : keccak256( + abi.encodePacked(typedDataSignTypehash(contentsName, contentsType), contentsHash, domainBytes) + ); + } + + /** + * @dev Variant of {typedDataSignStructHash-string-string-bytes32-bytes} that takes a content descriptor + * and decodes the `contentsName` and `contentsType` out of it. + */ + function typedDataSignStructHash( + string calldata contentsDescr, + bytes32 contentsHash, + bytes memory domainBytes + ) internal pure returns (bytes32 result) { + (string calldata contentsName, string calldata contentsType) = decodeContentsDescr(contentsDescr); + + return typedDataSignStructHash(contentsName, contentsType, contentsHash, domainBytes); + } + + /** + * @dev Compute the EIP-712 typehash of the `TypedDataSign` structure for a given type (and typename). + */ + function typedDataSignTypehash( + string calldata contentsName, + string calldata contentsType + ) internal pure returns (bytes32) { + return + keccak256( + abi.encodePacked( + "TypedDataSign(", + contentsName, + " contents,string name,string version,uint256 chainId,address verifyingContract,bytes32 salt)", + contentsType + ) + ); + } + + /** + * @dev Parse the type name out of the ERC-7739 contents type description. Supports both the implicit and explicit + * modes. + * + * Following ERC-7739 specifications, a `contentsName` is considered invalid if it's empty or it contains + * any of the following bytes , )\x00 + * + * If the `contentsType` is invalid, this returns an empty string. Otherwise, the return string has non-zero + * length. + */ + function decodeContentsDescr( + string calldata contentsDescr + ) internal pure returns (string calldata contentsName, string calldata contentsType) { + bytes calldata buffer = bytes(contentsDescr); + if (buffer.length == 0) { + // pass through (fail) + } else if (buffer[buffer.length - 1] == bytes1(")")) { + // Implicit mode: read contentsName from the beginning, and keep the complete descr + for (uint256 i = 0; i < buffer.length; ++i) { + bytes1 current = buffer[i]; + if (current == bytes1("(")) { + // if name is empty - passthrough (fail) + if (i == 0) break; + // we found the end of the contentsName + return (string(buffer[:i]), contentsDescr); + } else if (_isForbiddenChar(current)) { + // we found an invalid character (forbidden) - passthrough (fail) + break; + } + } + } else { + // Explicit mode: read contentsName from the end, and remove it from the descr + for (uint256 i = buffer.length; i > 0; --i) { + bytes1 current = buffer[i - 1]; + if (current == bytes1(")")) { + // we found the end of the contentsName + return (string(buffer[i:]), string(buffer[:i])); + } else if (_isForbiddenChar(current)) { + // we found an invalid character (forbidden) - passthrough (fail) + break; + } + } + } + return (Calldata.emptyString(), Calldata.emptyString()); + } + + function _isForbiddenChar(bytes1 char) private pure returns (bool) { + return char == 0x00 || char == bytes1(" ") || char == bytes1(",") || char == bytes1("(") || char == bytes1(")"); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/signers/AbstractSigner.sol b/dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/signers/AbstractSigner.sol new file mode 100644 index 00000000..942ec2a6 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/signers/AbstractSigner.sol @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (utils/cryptography/signers/AbstractSigner.sol) + +pragma solidity ^0.8.20; + +/** + * @dev Abstract contract for signature validation. + * + * Developers must implement {_rawSignatureValidation} and use it as the lowest-level signature validation mechanism. + * + * @custom:stateless + */ +abstract contract AbstractSigner { + /** + * @dev Signature validation algorithm. + * + * WARNING: Implementing a signature validation algorithm is a security-sensitive operation as it involves + * cryptographic verification. It is important to review and test thoroughly before deployment. Consider + * using one of the signature verification libraries (xref:api:utils/cryptography#ECDSA[ECDSA], + * xref:api:utils/cryptography#P256[P256] or xref:api:utils/cryptography#RSA[RSA]). + */ + function _rawSignatureValidation(bytes32 hash, bytes calldata signature) internal view virtual returns (bool); +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/signers/MultiSignerERC7913.sol b/dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/signers/MultiSignerERC7913.sol new file mode 100644 index 00000000..f485409b --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/signers/MultiSignerERC7913.sol @@ -0,0 +1,252 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (utils/cryptography/signers/MultiSignerERC7913.sol) + +pragma solidity ^0.8.26; + +import {AbstractSigner} from "./AbstractSigner.sol"; +import {SignatureChecker} from "../SignatureChecker.sol"; +import {EnumerableSet} from "../../structs/EnumerableSet.sol"; + +/** + * @dev Implementation of {AbstractSigner} using multiple ERC-7913 signers with a threshold-based + * signature verification system. + * + * This contract allows managing a set of authorized signers and requires a minimum number of + * signatures (threshold) to approve operations. It uses ERC-7913 formatted signers, which + * makes it natively compatible with ECDSA and ERC-1271 signers. + * + * Example of usage: + * + * ```solidity + * contract MyMultiSignerAccount is Account, MultiSignerERC7913, Initializable { + * function initialize(bytes[] memory signers, uint64 threshold) public initializer { + * _addSigners(signers); + * _setThreshold(threshold); + * } + * + * function addSigners(bytes[] memory signers) public onlyEntryPointOrSelf { + * _addSigners(signers); + * } + * + * function removeSigners(bytes[] memory signers) public onlyEntryPointOrSelf { + * _removeSigners(signers); + * } + * + * function setThreshold(uint64 threshold) public onlyEntryPointOrSelf { + * _setThreshold(threshold); + * } + * } + * ``` + * + * IMPORTANT: Failing to properly initialize the signers and threshold either during construction + * (if used standalone) or during initialization (if used as a clone) may leave the contract + * either front-runnable or unusable. + */ +abstract contract MultiSignerERC7913 is AbstractSigner { + using EnumerableSet for EnumerableSet.BytesSet; + using SignatureChecker for *; + + EnumerableSet.BytesSet private _signers; + uint64 private _threshold; + + /// @dev Emitted when a signer is added. + event ERC7913SignerAdded(bytes indexed signers); + + /// @dev Emitted when a signers is removed. + event ERC7913SignerRemoved(bytes indexed signers); + + /// @dev Emitted when the threshold is updated. + event ERC7913ThresholdSet(uint64 threshold); + + /// @dev The `signer` already exists. + error MultiSignerERC7913AlreadyExists(bytes signer); + + /// @dev The `signer` does not exist. + error MultiSignerERC7913NonexistentSigner(bytes signer); + + /// @dev The `signer` is less than 20 bytes long. + error MultiSignerERC7913InvalidSigner(bytes signer); + + /// @dev The `threshold` is zero. + error MultiSignerERC7913ZeroThreshold(); + + /// @dev The `threshold` is unreachable given the number of `signers`. + error MultiSignerERC7913UnreachableThreshold(uint64 signers, uint64 threshold); + + constructor(bytes[] memory signers_, uint64 threshold_) { + _addSigners(signers_); + _setThreshold(threshold_); + } + + /** + * @dev Returns a slice of the set of authorized signers. + * + * Using `start = 0` and `end = type(uint64).max` will return the entire set of signers. + * + * WARNING: Depending on the `start` and `end`, this operation can copy a large amount of data to memory, which + * can be expensive. This is designed for view accessors queried without gas fees. Using it in state-changing + * functions may become uncallable if the slice grows too large. + */ + function getSigners(uint64 start, uint64 end) public view virtual returns (bytes[] memory) { + return _signers.values(start, end); + } + + /// @dev Returns the number of authorized signers + function getSignerCount() public view virtual returns (uint256) { + return _signers.length(); + } + + /// @dev Returns whether the `signer` is an authorized signer. + function isSigner(bytes memory signer) public view virtual returns (bool) { + return _signers.contains(signer); + } + + /// @dev Returns the minimum number of signers required to approve a multisignature operation. + function threshold() public view virtual returns (uint64) { + return _threshold; + } + + /** + * @dev Adds the `newSigners` to those allowed to sign on behalf of this contract. + * Internal version without access control. + * + * Requirements: + * + * * Each of `newSigners` must be at least 20 bytes long. Reverts with {MultiSignerERC7913InvalidSigner} if not. + * * Each of `newSigners` must not be authorized. See {isSigner}. Reverts with {MultiSignerERC7913AlreadyExists} if so. + */ + function _addSigners(bytes[] memory newSigners) internal virtual { + for (uint256 i = 0; i < newSigners.length; ++i) { + bytes memory signer = newSigners[i]; + require(signer.length >= 20, MultiSignerERC7913InvalidSigner(signer)); + require(_signers.add(signer), MultiSignerERC7913AlreadyExists(signer)); + emit ERC7913SignerAdded(signer); + } + } + + /** + * @dev Removes the `oldSigners` from the authorized signers. Internal version without access control. + * + * Requirements: + * + * * Each of `oldSigners` must be authorized. See {isSigner}. Otherwise {MultiSignerERC7913NonexistentSigner} is thrown. + * * See {_validateReachableThreshold} for the threshold validation. + */ + function _removeSigners(bytes[] memory oldSigners) internal virtual { + for (uint256 i = 0; i < oldSigners.length; ++i) { + bytes memory signer = oldSigners[i]; + require(_signers.remove(signer), MultiSignerERC7913NonexistentSigner(signer)); + emit ERC7913SignerRemoved(signer); + } + _validateReachableThreshold(); + } + + /** + * @dev Sets the signatures `threshold` required to approve a multisignature operation. + * Internal version without access control. + * + * Requirements: + * + * * See {_validateReachableThreshold} for the threshold validation. + */ + function _setThreshold(uint64 newThreshold) internal virtual { + require(newThreshold > 0, MultiSignerERC7913ZeroThreshold()); + _threshold = newThreshold; + _validateReachableThreshold(); + emit ERC7913ThresholdSet(newThreshold); + } + + /** + * @dev Validates the current threshold is reachable. + * + * Requirements: + * + * * The {getSignerCount} must be greater or equal than to the {threshold}. Throws + * {MultiSignerERC7913UnreachableThreshold} if not. + */ + function _validateReachableThreshold() internal view virtual { + uint256 signersLength = _signers.length(); + uint64 currentThreshold = threshold(); + require( + signersLength >= currentThreshold, + MultiSignerERC7913UnreachableThreshold( + uint64(signersLength), // Safe cast. Economically impossible to overflow. + currentThreshold + ) + ); + } + + /** + * @dev Decodes, validates the signature and checks the signers are authorized. + * See {_validateSignatures} and {_validateThreshold} for more details. + * + * Example of signature encoding: + * + * ```solidity + * // Encode signers (verifier || key) + * bytes memory signer1 = abi.encodePacked(verifier1, key1); + * bytes memory signer2 = abi.encodePacked(verifier2, key2); + * + * // Order signers by their id + * if (keccak256(signer1) > keccak256(signer2)) { + * (signer1, signer2) = (signer2, signer1); + * (signature1, signature2) = (signature2, signature1); + * } + * + * // Assign ordered signers and signatures + * bytes[] memory signers = new bytes[](2); + * bytes[] memory signatures = new bytes[](2); + * signers[0] = signer1; + * signatures[0] = signature1; + * signers[1] = signer2; + * signatures[1] = signature2; + * + * // Encode the multi signature + * bytes memory signature = abi.encode(signers, signatures); + * ``` + * + * Requirements: + * + * * The `signature` must be encoded as `abi.encode(signers, signatures)`. + */ + function _rawSignatureValidation( + bytes32 hash, + bytes calldata signature + ) internal view virtual override returns (bool) { + if (signature.length == 0) return false; // For ERC-7739 compatibility + (bytes[] memory signers, bytes[] memory signatures) = abi.decode(signature, (bytes[], bytes[])); + return _validateThreshold(signers) && _validateSignatures(hash, signers, signatures); + } + + /** + * @dev Validates the signatures using the signers and their corresponding signatures. + * Returns whether the signers are authorized and the signatures are valid for the given hash. + * + * IMPORTANT: Sorting the signers by their `keccak256` hash will improve the gas efficiency of this function. + * See {SignatureChecker-areValidSignaturesNow-bytes32-bytes[]-bytes[]} for more details. + * + * Requirements: + * + * * The `signatures` and `signers` arrays must be equal in length. Returns false otherwise. + */ + function _validateSignatures( + bytes32 hash, + bytes[] memory signers, + bytes[] memory signatures + ) internal view virtual returns (bool valid) { + for (uint256 i = 0; i < signers.length; ++i) { + if (!isSigner(signers[i])) { + return false; + } + } + return hash.areValidSignaturesNow(signers, signatures); + } + + /** + * @dev Validates that the number of signers meets the {threshold} requirement. + * Assumes the signers were already validated. See {_validateSignatures} for more details. + */ + function _validateThreshold(bytes[] memory validatingSigners) internal view virtual returns (bool) { + return validatingSigners.length >= threshold(); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/signers/MultiSignerERC7913Weighted.sol b/dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/signers/MultiSignerERC7913Weighted.sol new file mode 100644 index 00000000..653272f9 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/signers/MultiSignerERC7913Weighted.sol @@ -0,0 +1,208 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (utils/cryptography/signers/MultiSignerERC7913Weighted.sol) + +pragma solidity ^0.8.26; + +import {SafeCast} from "../../math/SafeCast.sol"; +import {MultiSignerERC7913} from "./MultiSignerERC7913.sol"; + +/** + * @dev Extension of {MultiSignerERC7913} that supports weighted signatures. + * + * This contract allows assigning different weights to each signer, enabling more + * flexible governance schemes. For example, some signers could have higher weight + * than others, allowing for weighted voting or prioritized authorization. + * + * Example of usage: + * + * ```solidity + * contract MyWeightedMultiSignerAccount is Account, MultiSignerERC7913Weighted, Initializable { + * function initialize(bytes[] memory signers, uint64[] memory weights, uint64 threshold) public initializer { + * _addSigners(signers); + * _setSignerWeights(signers, weights); + * _setThreshold(threshold); + * } + * + * function addSigners(bytes[] memory signers) public onlyEntryPointOrSelf { + * _addSigners(signers); + * } + * + * function removeSigners(bytes[] memory signers) public onlyEntryPointOrSelf { + * _removeSigners(signers); + * } + * + * function setThreshold(uint64 threshold) public onlyEntryPointOrSelf { + * _setThreshold(threshold); + * } + * + * function setSignerWeights(bytes[] memory signers, uint64[] memory weights) public onlyEntryPointOrSelf { + * _setSignerWeights(signers, weights); + * } + * } + * ``` + * + * IMPORTANT: When setting a threshold value, ensure it matches the scale used for signer weights. + * For example, if signers have weights like 1, 2, or 3, then a threshold of 4 would require at + * least two signers (e.g., one with weight 1 and one with weight 3). See {signerWeight}. + */ +abstract contract MultiSignerERC7913Weighted is MultiSignerERC7913 { + using SafeCast for *; + + // Sum of all the extra weights of all signers. Storage packed with `MultiSignerERC7913._threshold` + uint64 private _totalExtraWeight; + + // Mapping from signer to extraWeight (in addition to all authorized signers having weight 1) + mapping(bytes signer => uint64) private _extraWeights; + + /** + * @dev Emitted when a signer's weight is changed. + * + * NOTE: Not emitted in {_addSigners} or {_removeSigners}. Indexers must rely on {ERC7913SignerAdded} + * and {ERC7913SignerRemoved} to index a default weight of 1. See {signerWeight}. + */ + event ERC7913SignerWeightChanged(bytes indexed signer, uint64 weight); + + /// @dev Thrown when a signer's weight is invalid. + error MultiSignerERC7913WeightedInvalidWeight(bytes signer, uint64 weight); + + /// @dev Thrown when the arrays lengths don't match. See {_setSignerWeights}. + error MultiSignerERC7913WeightedMismatchedLength(); + + constructor(bytes[] memory signers_, uint64[] memory weights_, uint64 threshold_) MultiSignerERC7913(signers_, 1) { + _setSignerWeights(signers_, weights_); + _setThreshold(threshold_); + } + + /// @dev Gets the weight of a signer. Returns 0 if the signer is not authorized. + function signerWeight(bytes memory signer) public view virtual returns (uint64) { + unchecked { + // Safe cast, _setSignerWeights guarantees 1+_extraWeights is a uint64 + return uint64(isSigner(signer).toUint() * (1 + _extraWeights[signer])); + } + } + + /// @dev Gets the total weight of all signers. + function totalWeight() public view virtual returns (uint64) { + return (getSignerCount() + _totalExtraWeight).toUint64(); + } + + /** + * @dev Sets weights for multiple signers at once. Internal version without access control. + * + * Requirements: + * + * * `signers` and `weights` arrays must have the same length. Reverts with {MultiSignerERC7913WeightedMismatchedLength} on mismatch. + * * Each signer must exist in the set of authorized signers. Otherwise reverts with {MultiSignerERC7913NonexistentSigner} + * * Each weight must be greater than 0. Otherwise reverts with {MultiSignerERC7913WeightedInvalidWeight} + * * See {_validateReachableThreshold} for the threshold validation. + * + * Emits {ERC7913SignerWeightChanged} for each signer. + */ + function _setSignerWeights(bytes[] memory signers, uint64[] memory weights) internal virtual { + require(signers.length == weights.length, MultiSignerERC7913WeightedMismatchedLength()); + + uint256 extraWeightAdded = 0; + uint256 extraWeightRemoved = 0; + for (uint256 i = 0; i < signers.length; ++i) { + bytes memory signer = signers[i]; + require(isSigner(signer), MultiSignerERC7913NonexistentSigner(signer)); + + uint64 weight = weights[i]; + require(weight > 0, MultiSignerERC7913WeightedInvalidWeight(signer, weight)); + + unchecked { + uint64 oldExtraWeight = _extraWeights[signer]; + uint64 newExtraWeight = weight - 1; + + if (oldExtraWeight != newExtraWeight) { + // Overflow impossible: weight values are bounded by uint64 and economic constraints + extraWeightRemoved += oldExtraWeight; + extraWeightAdded += _extraWeights[signer] = newExtraWeight; + emit ERC7913SignerWeightChanged(signer, weight); + } + } + } + unchecked { + // Safe from underflow: `extraWeightRemoved` is bounded by `_totalExtraWeight` by construction + // and weight values are bounded by uint64 and economic constraints + _totalExtraWeight = (uint256(_totalExtraWeight) + extraWeightAdded - extraWeightRemoved).toUint64(); + } + _validateReachableThreshold(); + } + + /** + * @dev See {MultiSignerERC7913-_addSigners}. + * + * In cases where {totalWeight} is almost `type(uint64).max` (due to a large `_totalExtraWeight`), adding new + * signers could cause the {totalWeight} computation to overflow. Adding a {totalWeight} calls after the new + * signers are added ensures no such overflow happens. + */ + function _addSigners(bytes[] memory newSigners) internal virtual override { + super._addSigners(newSigners); + + // This will revert if the new signers cause an overflow + _validateReachableThreshold(); + } + + /** + * @dev See {MultiSignerERC7913-_removeSigners}. + * + * Just like {_addSigners}, this function does not emit {ERC7913SignerWeightChanged} events. The + * {ERC7913SignerRemoved} event emitted by {MultiSignerERC7913-_removeSigners} is enough to track weights here. + */ + function _removeSigners(bytes[] memory signers) internal virtual override { + // Clean up weights for removed signers + // + // The `extraWeightRemoved` is bounded by `_totalExtraWeight`. The `super._removeSigners` function will revert + // if the signers array contains any duplicates, ensuring each signer's weight is only counted once. Since + // `_totalExtraWeight` is stored as a `uint64`, the final subtraction operation is also safe. + unchecked { + uint64 extraWeightRemoved = 0; + for (uint256 i = 0; i < signers.length; ++i) { + bytes memory signer = signers[i]; + + extraWeightRemoved += _extraWeights[signer]; + delete _extraWeights[signer]; + } + _totalExtraWeight -= extraWeightRemoved; + } + super._removeSigners(signers); + } + + /** + * @dev Sets the threshold for the multisignature operation. Internal version without access control. + * + * Requirements: + * + * * The {totalWeight} must be `>=` the {threshold}. Otherwise reverts with {MultiSignerERC7913UnreachableThreshold} + * + * NOTE: This function intentionally does not call `super._validateReachableThreshold` because the base implementation + * assumes each signer has a weight of 1, which is a subset of this weighted implementation. Consider that multiple + * implementations of this function may exist in the contract, so important side effects may be missed + * depending on the linearization order. + */ + function _validateReachableThreshold() internal view virtual override { + uint64 weight = totalWeight(); + uint64 currentThreshold = threshold(); + require(weight >= currentThreshold, MultiSignerERC7913UnreachableThreshold(weight, currentThreshold)); + } + + /** + * @dev Validates that the total weight of signers meets the threshold requirement. + * + * NOTE: This function intentionally does not call `super._validateThreshold` because the base implementation + * assumes each signer has a weight of 1, which is a subset of this weighted implementation. Consider that multiple + * implementations of this function may exist in the contract, so important side effects may be missed + * depending on the linearization order. + */ + function _validateThreshold(bytes[] memory signers) internal view virtual override returns (bool) { + unchecked { + uint64 weight = 0; + for (uint256 i = 0; i < signers.length; ++i) { + // Overflow impossible: weight values are bounded by uint64 and economic constraints + weight += signerWeight(signers[i]); + } + return weight >= threshold(); + } + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/signers/SignerECDSA.sol b/dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/signers/SignerECDSA.sol new file mode 100644 index 00000000..517cd7e7 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/signers/SignerECDSA.sol @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (utils/cryptography/signers/SignerECDSA.sol) + +pragma solidity ^0.8.20; + +import {AbstractSigner} from "./AbstractSigner.sol"; +import {ECDSA} from "../ECDSA.sol"; + +/** + * @dev Implementation of {AbstractSigner} using xref:api:utils/cryptography#ECDSA[ECDSA] signatures. + * + * For {Account} usage, a {_setSigner} function is provided to set the {signer} address. + * Doing so is easier for a factory, who is likely to use initializable clones of this contract. + * + * Example of usage: + * + * ```solidity + * contract MyAccountECDSA is Account, SignerECDSA, Initializable { + * function initialize(address signerAddr) public initializer { + * _setSigner(signerAddr); + * } + * } + * ``` + * + * IMPORTANT: Failing to call {_setSigner} either during construction (if used standalone) + * or during initialization (if used as a clone) may leave the signer either front-runnable or unusable. + */ +abstract contract SignerECDSA is AbstractSigner { + address private _signer; + + constructor(address signerAddr) { + _setSigner(signerAddr); + } + + /** + * @dev Sets the signer with the address of the native signer. This function should be called during construction + * or through an initializer. + */ + function _setSigner(address signerAddr) internal { + _signer = signerAddr; + } + + /// @dev Return the signer's address. + function signer() public view virtual returns (address) { + return _signer; + } + + /// @inheritdoc AbstractSigner + function _rawSignatureValidation( + bytes32 hash, + bytes calldata signature + ) internal view virtual override returns (bool) { + (address recovered, ECDSA.RecoverError err, ) = ECDSA.tryRecover(hash, signature); + return signer() == recovered && err == ECDSA.RecoverError.NoError; + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/signers/SignerERC7702.sol b/dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/signers/SignerERC7702.sol new file mode 100644 index 00000000..b02190e1 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/signers/SignerERC7702.sol @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (utils/cryptography/signers/SignerERC7702.sol) + +pragma solidity ^0.8.20; + +import {AbstractSigner} from "./AbstractSigner.sol"; +import {ECDSA} from "../ECDSA.sol"; + +/** + * @dev Implementation of {AbstractSigner} for implementation for an EOA. Useful for ERC-7702 accounts. + * + * @custom:stateless + */ +abstract contract SignerERC7702 is AbstractSigner { + /** + * @dev Validates the signature using the EOA's address (i.e. `address(this)`). + */ + function _rawSignatureValidation( + bytes32 hash, + bytes calldata signature + ) internal view virtual override returns (bool) { + (address recovered, ECDSA.RecoverError err, ) = ECDSA.tryRecover(hash, signature); + return address(this) == recovered && err == ECDSA.RecoverError.NoError; + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/signers/SignerERC7913.sol b/dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/signers/SignerERC7913.sol new file mode 100644 index 00000000..d0f567a3 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/signers/SignerERC7913.sol @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (utils/cryptography/signers/SignerERC7913.sol) + +pragma solidity ^0.8.24; + +import {AbstractSigner} from "./AbstractSigner.sol"; +import {SignatureChecker} from "../SignatureChecker.sol"; + +/** + * @dev Implementation of {AbstractSigner} using + * https://eips.ethereum.org/EIPS/eip-7913[ERC-7913] signature verification. + * + * For {Account} usage, a {_setSigner} function is provided to set the ERC-7913 formatted {signer}. + * Doing so is easier for a factory, who is likely to use initializable clones of this contract. + * + * The signer is a `bytes` object that concatenates a verifier address and a key: `verifier || key`. + * + * Example of usage: + * + * ```solidity + * contract MyAccountERC7913 is Account, SignerERC7913, Initializable { + * function initialize(bytes memory signer_) public initializer { + * _setSigner(signer_); + * } + * + * function setSigner(bytes memory signer_) public onlyEntryPointOrSelf { + * _setSigner(signer_); + * } + * } + * ``` + * + * IMPORTANT: Failing to call {_setSigner} either during construction (if used standalone) + * or during initialization (if used as a clone) may leave the signer either front-runnable or unusable. + */ + +abstract contract SignerERC7913 is AbstractSigner { + bytes private _signer; + + constructor(bytes memory signer_) { + _setSigner(signer_); + } + + /// @dev Return the ERC-7913 signer (i.e. `verifier || key`). + function signer() public view virtual returns (bytes memory) { + return _signer; + } + + /// @dev Sets the signer (i.e. `verifier || key`) with an ERC-7913 formatted signer. + function _setSigner(bytes memory signer_) internal { + _signer = signer_; + } + + /** + * @dev Verifies a signature using {SignatureChecker-isValidSignatureNow-bytes-bytes32-bytes-} + * with {signer}, `hash` and `signature`. + */ + function _rawSignatureValidation( + bytes32 hash, + bytes calldata signature + ) internal view virtual override returns (bool) { + return SignatureChecker.isValidSignatureNow(signer(), hash, signature); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/signers/SignerP256.sol b/dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/signers/SignerP256.sol new file mode 100644 index 00000000..131b5c1f --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/signers/SignerP256.sol @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (utils/cryptography/signers/SignerP256.sol) + +pragma solidity ^0.8.20; + +import {AbstractSigner} from "./AbstractSigner.sol"; +import {P256} from "../P256.sol"; + +/** + * @dev Implementation of {AbstractSigner} using xref:api:utils/cryptography#P256[P256] signatures. + * + * For {Account} usage, a {_setSigner} function is provided to set the {signer} public key. + * Doing so is easier for a factory, who is likely to use initializable clones of this contract. + * + * Example of usage: + * + * ```solidity + * contract MyAccountP256 is Account, SignerP256, Initializable { + * function initialize(bytes32 qx, bytes32 qy) public initializer { + * _setSigner(qx, qy); + * } + * } + * ``` + * + * IMPORTANT: Failing to call {_setSigner} either during construction (if used standalone) + * or during initialization (if used as a clone) may leave the signer either front-runnable or unusable. + */ +abstract contract SignerP256 is AbstractSigner { + bytes32 private _qx; + bytes32 private _qy; + + error SignerP256InvalidPublicKey(bytes32 qx, bytes32 qy); + + constructor(bytes32 qx, bytes32 qy) { + _setSigner(qx, qy); + } + + /** + * @dev Sets the signer with a P256 public key. This function should be called during construction + * or through an initializer. + */ + function _setSigner(bytes32 qx, bytes32 qy) internal { + if (!P256.isValidPublicKey(qx, qy)) revert SignerP256InvalidPublicKey(qx, qy); + _qx = qx; + _qy = qy; + } + + /// @dev Return the signer's P256 public key. + function signer() public view virtual returns (bytes32 qx, bytes32 qy) { + return (_qx, _qy); + } + + /// @inheritdoc AbstractSigner + function _rawSignatureValidation( + bytes32 hash, + bytes calldata signature + ) internal view virtual override returns (bool) { + if (signature.length < 0x40) return false; + bytes32 r = bytes32(signature[0x00:0x20]); + bytes32 s = bytes32(signature[0x20:0x40]); + (bytes32 qx, bytes32 qy) = signer(); + return P256.verify(hash, r, s, qx, qy); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/signers/SignerRSA.sol b/dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/signers/SignerRSA.sol new file mode 100644 index 00000000..7ca18ead --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/signers/SignerRSA.sol @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (utils/cryptography/signers/SignerRSA.sol) + +pragma solidity ^0.8.20; + +import {AbstractSigner} from "./AbstractSigner.sol"; +import {RSA} from "../RSA.sol"; + +/** + * @dev Implementation of {AbstractSigner} using xref:api:utils/cryptography#RSA[RSA] signatures. + * + * For {Account} usage, a {_setSigner} function is provided to set the {signer} public key. + * Doing so is easier for a factory, who is likely to use initializable clones of this contract. + * + * Example of usage: + * + * ```solidity + * contract MyAccountRSA is Account, SignerRSA, Initializable { + * function initialize(bytes memory e, bytes memory n) public initializer { + * _setSigner(e, n); + * } + * } + * ``` + * + * IMPORTANT: Failing to call {_setSigner} either during construction (if used standalone) + * or during initialization (if used as a clone) may leave the signer either front-runnable or unusable. + */ +abstract contract SignerRSA is AbstractSigner { + bytes private _e; + bytes private _n; + + constructor(bytes memory e, bytes memory n) { + _setSigner(e, n); + } + + /** + * @dev Sets the signer with a RSA public key. This function should be called during construction + * or through an initializer. + */ + function _setSigner(bytes memory e, bytes memory n) internal { + _e = e; + _n = n; + } + + /// @dev Return the signer's RSA public key. + function signer() public view virtual returns (bytes memory e, bytes memory n) { + return (_e, _n); + } + + /** + * @dev See {AbstractSigner-_rawSignatureValidation}. Verifies a PKCSv1.5 signature by calling + * xref:api:utils/cryptography.adoc#RSA-pkcs1Sha256-bytes-bytes-bytes-bytes-[RSA.pkcs1Sha256]. + * + * IMPORTANT: Following the RSASSA-PKCS1-V1_5-VERIFY procedure outlined in RFC8017 (section 8.2.2), the + * provided `hash` is used as the `M` (message) and rehashed using SHA256 according to EMSA-PKCS1-v1_5 + * encoding as per section 9.2 (step 1) of the RFC. + */ + function _rawSignatureValidation( + bytes32 hash, + bytes calldata signature + ) internal view virtual override returns (bool) { + (bytes memory e, bytes memory n) = signer(); + return RSA.pkcs1Sha256(abi.encodePacked(hash), signature, e, n); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/signers/draft-ERC7739.sol b/dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/signers/draft-ERC7739.sol new file mode 100644 index 00000000..003b9157 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/signers/draft-ERC7739.sol @@ -0,0 +1,99 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (utils/cryptography/signers/draft-ERC7739.sol) + +pragma solidity ^0.8.20; + +import {AbstractSigner} from "./AbstractSigner.sol"; +import {EIP712} from "../EIP712.sol"; +import {ERC7739Utils} from "../draft-ERC7739Utils.sol"; +import {IERC1271} from "../../../interfaces/IERC1271.sol"; +import {MessageHashUtils} from "../MessageHashUtils.sol"; +import {ShortStrings} from "../../ShortStrings.sol"; + +/** + * @dev Validates signatures wrapping the message hash in a nested EIP712 type. See {ERC7739Utils}. + * + * Linking the signature to the EIP-712 domain separator is a security measure to prevent signature replay across different + * EIP-712 domains (e.g. a single offchain owner of multiple contracts). + * + * This contract requires implementing the {_rawSignatureValidation} function, which passes the wrapped message hash, + * which may be either an typed data or a personal sign nested type. + * + * NOTE: xref:api:utils/cryptography#EIP712[EIP-712] uses xref:api:utils/cryptography#ShortStrings[ShortStrings] to + * optimize gas costs for short strings (up to 31 characters). Consider that strings longer than that will use storage, + * which may limit the ability of the signer to be used within the ERC-4337 validation phase (due to + * https://eips.ethereum.org/EIPS/eip-7562#storage-rules[ERC-7562 storage access rules]). + */ +abstract contract ERC7739 is AbstractSigner, EIP712, IERC1271 { + using ERC7739Utils for *; + using MessageHashUtils for bytes32; + + /** + * @dev Attempts validating the signature in a nested EIP-712 type. + * + * A nested EIP-712 type might be presented in 2 different ways: + * + * - As a nested EIP-712 typed data + * - As a _personal_ signature (an EIP-712 mimic of the `eth_personalSign` for a smart contract) + */ + function isValidSignature(bytes32 hash, bytes calldata signature) public view virtual returns (bytes4 result) { + // For the hash `0x7739773977397739773977397739773977397739773977397739773977397739` and an empty signature, + // we return the magic value `0x77390001` as it's assumed impossible to find a preimage for it that can be used + // maliciously. Useful for simulation purposes and to validate whether the contract supports ERC-7739. + return + (_isValidNestedTypedDataSignature(hash, signature) || _isValidNestedPersonalSignSignature(hash, signature)) + ? IERC1271.isValidSignature.selector + : (hash == 0x7739773977397739773977397739773977397739773977397739773977397739 && signature.length == 0) + ? bytes4(0x77390001) + : bytes4(0xffffffff); + } + + /** + * @dev Nested personal signature verification. + */ + function _isValidNestedPersonalSignSignature(bytes32 hash, bytes calldata signature) private view returns (bool) { + return _rawSignatureValidation(_domainSeparatorV4().toTypedDataHash(hash.personalSignStructHash()), signature); + } + + /** + * @dev Nested EIP-712 typed data verification. + */ + function _isValidNestedTypedDataSignature( + bytes32 hash, + bytes calldata encodedSignature + ) private view returns (bool) { + // decode signature + ( + bytes calldata signature, + bytes32 appSeparator, + bytes32 contentsHash, + string calldata contentsDescr + ) = encodedSignature.decodeTypedDataSig(); + + ( + , + string memory name, + string memory version, + uint256 chainId, + address verifyingContract, + bytes32 salt, + + ) = eip712Domain(); + + // Check that contentHash and separator are correct + // Rebuild nested hash + return + hash == appSeparator.toTypedDataHash(contentsHash) && + bytes(contentsDescr).length != 0 && + _rawSignatureValidation( + appSeparator.toTypedDataHash( + ERC7739Utils.typedDataSignStructHash( + contentsDescr, + contentsHash, + abi.encode(keccak256(bytes(name)), keccak256(bytes(version)), chainId, verifyingContract, salt) + ) + ), + signature + ); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/verifiers/ERC7913P256Verifier.sol b/dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/verifiers/ERC7913P256Verifier.sol new file mode 100644 index 00000000..60091c97 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/verifiers/ERC7913P256Verifier.sol @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (utils/cryptography/verifiers/ERC7913P256Verifier.sol) + +pragma solidity ^0.8.20; + +import {P256} from "../../../utils/cryptography/P256.sol"; +import {IERC7913SignatureVerifier} from "../../../interfaces/IERC7913.sol"; + +/** + * @dev ERC-7913 signature verifier that support P256 (secp256r1) keys. + * + * @custom:stateless + */ +contract ERC7913P256Verifier is IERC7913SignatureVerifier { + /// @inheritdoc IERC7913SignatureVerifier + function verify(bytes calldata key, bytes32 hash, bytes calldata signature) public view virtual returns (bytes4) { + // Signature length may be 0x40 or 0x41. + if (key.length == 0x40 && signature.length >= 0x40) { + bytes32 qx = bytes32(key[0x00:0x20]); + bytes32 qy = bytes32(key[0x20:0x40]); + bytes32 r = bytes32(signature[0x00:0x20]); + bytes32 s = bytes32(signature[0x20:0x40]); + if (P256.verify(hash, r, s, qx, qy)) { + return IERC7913SignatureVerifier.verify.selector; + } + } + return 0xFFFFFFFF; + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/verifiers/ERC7913RSAVerifier.sol b/dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/verifiers/ERC7913RSAVerifier.sol new file mode 100644 index 00000000..07f58c89 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/utils/cryptography/verifiers/ERC7913RSAVerifier.sol @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (utils/cryptography/verifiers/ERC7913RSAVerifier.sol) + +pragma solidity ^0.8.20; + +import {RSA} from "../../../utils/cryptography/RSA.sol"; +import {IERC7913SignatureVerifier} from "../../../interfaces/IERC7913.sol"; + +/** + * @dev ERC-7913 signature verifier that support RSA keys. + * + * @custom:stateless + */ +contract ERC7913RSAVerifier is IERC7913SignatureVerifier { + /// @inheritdoc IERC7913SignatureVerifier + function verify(bytes calldata key, bytes32 hash, bytes calldata signature) public view virtual returns (bytes4) { + (bytes memory e, bytes memory n) = abi.decode(key, (bytes, bytes)); + return + RSA.pkcs1Sha256(abi.encodePacked(hash), signature, e, n) + ? IERC7913SignatureVerifier.verify.selector + : bytes4(0xFFFFFFFF); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/utils/introspection/ERC165.sol b/dependencies/@openzeppelin-contracts-5.4.0/utils/introspection/ERC165.sol new file mode 100644 index 00000000..be4cc5a6 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/utils/introspection/ERC165.sol @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (utils/introspection/ERC165.sol) + +pragma solidity ^0.8.20; + +import {IERC165} from "./IERC165.sol"; + +/** + * @dev Implementation of the {IERC165} interface. + * + * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check + * for the additional interface id that will be supported. For example: + * + * ```solidity + * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { + * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); + * } + * ``` + */ +abstract contract ERC165 is IERC165 { + /// @inheritdoc IERC165 + function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { + return interfaceId == type(IERC165).interfaceId; + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/utils/introspection/ERC165Checker.sol b/dependencies/@openzeppelin-contracts-5.4.0/utils/introspection/ERC165Checker.sol new file mode 100644 index 00000000..8650f550 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/utils/introspection/ERC165Checker.sol @@ -0,0 +1,124 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165Checker.sol) + +pragma solidity ^0.8.20; + +import {IERC165} from "./IERC165.sol"; + +/** + * @dev Library used to query support of an interface declared via {IERC165}. + * + * Note that these functions return the actual result of the query: they do not + * `revert` if an interface is not supported. It is up to the caller to decide + * what to do in these cases. + */ +library ERC165Checker { + // As per the ERC-165 spec, no interface should ever match 0xffffffff + bytes4 private constant INTERFACE_ID_INVALID = 0xffffffff; + + /** + * @dev Returns true if `account` supports the {IERC165} interface. + */ + function supportsERC165(address account) internal view returns (bool) { + // Any contract that implements ERC-165 must explicitly indicate support of + // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid + return + supportsERC165InterfaceUnchecked(account, type(IERC165).interfaceId) && + !supportsERC165InterfaceUnchecked(account, INTERFACE_ID_INVALID); + } + + /** + * @dev Returns true if `account` supports the interface defined by + * `interfaceId`. Support for {IERC165} itself is queried automatically. + * + * See {IERC165-supportsInterface}. + */ + function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) { + // query support of both ERC-165 as per the spec and support of _interfaceId + return supportsERC165(account) && supportsERC165InterfaceUnchecked(account, interfaceId); + } + + /** + * @dev Returns a boolean array where each value corresponds to the + * interfaces passed in and whether they're supported or not. This allows + * you to batch check interfaces for a contract where your expectation + * is that some interfaces may not be supported. + * + * See {IERC165-supportsInterface}. + */ + function getSupportedInterfaces( + address account, + bytes4[] memory interfaceIds + ) internal view returns (bool[] memory) { + // an array of booleans corresponding to interfaceIds and whether they're supported or not + bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length); + + // query support of ERC-165 itself + if (supportsERC165(account)) { + // query support of each interface in interfaceIds + for (uint256 i = 0; i < interfaceIds.length; i++) { + interfaceIdsSupported[i] = supportsERC165InterfaceUnchecked(account, interfaceIds[i]); + } + } + + return interfaceIdsSupported; + } + + /** + * @dev Returns true if `account` supports all the interfaces defined in + * `interfaceIds`. Support for {IERC165} itself is queried automatically. + * + * Batch-querying can lead to gas savings by skipping repeated checks for + * {IERC165} support. + * + * See {IERC165-supportsInterface}. + */ + function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) { + // query support of ERC-165 itself + if (!supportsERC165(account)) { + return false; + } + + // query support of each interface in interfaceIds + for (uint256 i = 0; i < interfaceIds.length; i++) { + if (!supportsERC165InterfaceUnchecked(account, interfaceIds[i])) { + return false; + } + } + + // all interfaces supported + return true; + } + + /** + * @notice Query if a contract implements an interface, does not check ERC-165 support + * @param account The address of the contract to query for support of an interface + * @param interfaceId The interface identifier, as specified in ERC-165 + * @return true if the contract at account indicates support of the interface with + * identifier interfaceId, false otherwise + * @dev Assumes that account contains a contract that supports ERC-165, otherwise + * the behavior of this method is undefined. This precondition can be checked + * with {supportsERC165}. + * + * Some precompiled contracts will falsely indicate support for a given interface, so caution + * should be exercised when using this function. + * + * Interface identification is specified in ERC-165. + */ + function supportsERC165InterfaceUnchecked(address account, bytes4 interfaceId) internal view returns (bool) { + // prepare call + bytes memory encodedParams = abi.encodeCall(IERC165.supportsInterface, (interfaceId)); + + // perform static call + bool success; + uint256 returnSize; + uint256 returnValue; + assembly ("memory-safe") { + success := staticcall(30000, account, add(encodedParams, 0x20), mload(encodedParams), 0x00, 0x20) + returnSize := returndatasize() + returnValue := mload(0x00) + } + + return success && returnSize >= 0x20 && returnValue > 0; + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/utils/introspection/IERC165.sol b/dependencies/@openzeppelin-contracts-5.4.0/utils/introspection/IERC165.sol new file mode 100644 index 00000000..be1932f2 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/utils/introspection/IERC165.sol @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (utils/introspection/IERC165.sol) + +pragma solidity >=0.4.16; + +/** + * @dev Interface of the ERC-165 standard, as defined in the + * https://eips.ethereum.org/EIPS/eip-165[ERC]. + * + * Implementers can declare support of contract interfaces, which can then be + * queried by others ({ERC165Checker}). + * + * For an implementation, see {ERC165}. + */ +interface IERC165 { + /** + * @dev Returns true if this contract implements the interface defined by + * `interfaceId`. See the corresponding + * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section] + * to learn more about how these ids are created. + * + * This function call must use less than 30 000 gas. + */ + function supportsInterface(bytes4 interfaceId) external view returns (bool); +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/utils/math/Math.sol b/dependencies/@openzeppelin-contracts-5.4.0/utils/math/Math.sol new file mode 100644 index 00000000..f0d608a2 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/utils/math/Math.sol @@ -0,0 +1,749 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.3.0) (utils/math/Math.sol) + +pragma solidity ^0.8.20; + +import {Panic} from "../Panic.sol"; +import {SafeCast} from "./SafeCast.sol"; + +/** + * @dev Standard math utilities missing in the Solidity language. + */ +library Math { + enum Rounding { + Floor, // Toward negative infinity + Ceil, // Toward positive infinity + Trunc, // Toward zero + Expand // Away from zero + } + + /** + * @dev Return the 512-bit addition of two uint256. + * + * The result is stored in two 256 variables such that sum = high * 2²⁵⁶ + low. + */ + function add512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) { + assembly ("memory-safe") { + low := add(a, b) + high := lt(low, a) + } + } + + /** + * @dev Return the 512-bit multiplication of two uint256. + * + * The result is stored in two 256 variables such that product = high * 2²⁵⁶ + low. + */ + function mul512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) { + // 512-bit multiply [high low] = x * y. Compute the product mod 2²⁵⁶ and mod 2²⁵⁶ - 1, then use + // the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 + // variables such that product = high * 2²⁵⁶ + low. + assembly ("memory-safe") { + let mm := mulmod(a, b, not(0)) + low := mul(a, b) + high := sub(sub(mm, low), lt(mm, low)) + } + } + + /** + * @dev Returns the addition of two unsigned integers, with a success flag (no overflow). + */ + function tryAdd(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) { + unchecked { + uint256 c = a + b; + success = c >= a; + result = c * SafeCast.toUint(success); + } + } + + /** + * @dev Returns the subtraction of two unsigned integers, with a success flag (no overflow). + */ + function trySub(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) { + unchecked { + uint256 c = a - b; + success = c <= a; + result = c * SafeCast.toUint(success); + } + } + + /** + * @dev Returns the multiplication of two unsigned integers, with a success flag (no overflow). + */ + function tryMul(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) { + unchecked { + uint256 c = a * b; + assembly ("memory-safe") { + // Only true when the multiplication doesn't overflow + // (c / a == b) || (a == 0) + success := or(eq(div(c, a), b), iszero(a)) + } + // equivalent to: success ? c : 0 + result = c * SafeCast.toUint(success); + } + } + + /** + * @dev Returns the division of two unsigned integers, with a success flag (no division by zero). + */ + function tryDiv(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) { + unchecked { + success = b > 0; + assembly ("memory-safe") { + // The `DIV` opcode returns zero when the denominator is 0. + result := div(a, b) + } + } + } + + /** + * @dev Returns the remainder of dividing two unsigned integers, with a success flag (no division by zero). + */ + function tryMod(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) { + unchecked { + success = b > 0; + assembly ("memory-safe") { + // The `MOD` opcode returns zero when the denominator is 0. + result := mod(a, b) + } + } + } + + /** + * @dev Unsigned saturating addition, bounds to `2²⁵⁶ - 1` instead of overflowing. + */ + function saturatingAdd(uint256 a, uint256 b) internal pure returns (uint256) { + (bool success, uint256 result) = tryAdd(a, b); + return ternary(success, result, type(uint256).max); + } + + /** + * @dev Unsigned saturating subtraction, bounds to zero instead of overflowing. + */ + function saturatingSub(uint256 a, uint256 b) internal pure returns (uint256) { + (, uint256 result) = trySub(a, b); + return result; + } + + /** + * @dev Unsigned saturating multiplication, bounds to `2²⁵⁶ - 1` instead of overflowing. + */ + function saturatingMul(uint256 a, uint256 b) internal pure returns (uint256) { + (bool success, uint256 result) = tryMul(a, b); + return ternary(success, result, type(uint256).max); + } + + /** + * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant. + * + * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone. + * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute + * one branch when needed, making this function more expensive. + */ + function ternary(bool condition, uint256 a, uint256 b) internal pure returns (uint256) { + unchecked { + // branchless ternary works because: + // b ^ (a ^ b) == a + // b ^ 0 == b + return b ^ ((a ^ b) * SafeCast.toUint(condition)); + } + } + + /** + * @dev Returns the largest of two numbers. + */ + function max(uint256 a, uint256 b) internal pure returns (uint256) { + return ternary(a > b, a, b); + } + + /** + * @dev Returns the smallest of two numbers. + */ + function min(uint256 a, uint256 b) internal pure returns (uint256) { + return ternary(a < b, a, b); + } + + /** + * @dev Returns the average of two numbers. The result is rounded towards + * zero. + */ + function average(uint256 a, uint256 b) internal pure returns (uint256) { + // (a + b) / 2 can overflow. + return (a & b) + (a ^ b) / 2; + } + + /** + * @dev Returns the ceiling of the division of two numbers. + * + * This differs from standard division with `/` in that it rounds towards infinity instead + * of rounding towards zero. + */ + function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { + if (b == 0) { + // Guarantee the same behavior as in a regular Solidity division. + Panic.panic(Panic.DIVISION_BY_ZERO); + } + + // The following calculation ensures accurate ceiling division without overflow. + // Since a is non-zero, (a - 1) / b will not overflow. + // The largest possible result occurs when (a - 1) / b is type(uint256).max, + // but the largest value we can obtain is type(uint256).max - 1, which happens + // when a = type(uint256).max and b = 1. + unchecked { + return SafeCast.toUint(a > 0) * ((a - 1) / b + 1); + } + } + + /** + * @dev Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or + * denominator == 0. + * + * Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by + * Uniswap Labs also under MIT license. + */ + function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { + unchecked { + (uint256 high, uint256 low) = mul512(x, y); + + // Handle non-overflow cases, 256 by 256 division. + if (high == 0) { + // Solidity will revert if denominator == 0, unlike the div opcode on its own. + // The surrounding unchecked block does not change this fact. + // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. + return low / denominator; + } + + // Make sure the result is less than 2²⁵⁶. Also prevents denominator == 0. + if (denominator <= high) { + Panic.panic(ternary(denominator == 0, Panic.DIVISION_BY_ZERO, Panic.UNDER_OVERFLOW)); + } + + /////////////////////////////////////////////// + // 512 by 256 division. + /////////////////////////////////////////////// + + // Make division exact by subtracting the remainder from [high low]. + uint256 remainder; + assembly ("memory-safe") { + // Compute remainder using mulmod. + remainder := mulmod(x, y, denominator) + + // Subtract 256 bit number from 512 bit number. + high := sub(high, gt(remainder, low)) + low := sub(low, remainder) + } + + // Factor powers of two out of denominator and compute largest power of two divisor of denominator. + // Always >= 1. See https://cs.stackexchange.com/q/138556/92363. + + uint256 twos = denominator & (0 - denominator); + assembly ("memory-safe") { + // Divide denominator by twos. + denominator := div(denominator, twos) + + // Divide [high low] by twos. + low := div(low, twos) + + // Flip twos such that it is 2²⁵⁶ / twos. If twos is zero, then it becomes one. + twos := add(div(sub(0, twos), twos), 1) + } + + // Shift in bits from high into low. + low |= high * twos; + + // Invert denominator mod 2²⁵⁶. Now that denominator is an odd number, it has an inverse modulo 2²⁵⁶ such + // that denominator * inv ≡ 1 mod 2²⁵⁶. Compute the inverse by starting with a seed that is correct for + // four bits. That is, denominator * inv ≡ 1 mod 2⁴. + uint256 inverse = (3 * denominator) ^ 2; + + // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also + // works in modular arithmetic, doubling the correct bits in each step. + inverse *= 2 - denominator * inverse; // inverse mod 2⁸ + inverse *= 2 - denominator * inverse; // inverse mod 2¹⁶ + inverse *= 2 - denominator * inverse; // inverse mod 2³² + inverse *= 2 - denominator * inverse; // inverse mod 2⁶⁴ + inverse *= 2 - denominator * inverse; // inverse mod 2¹²⁸ + inverse *= 2 - denominator * inverse; // inverse mod 2²⁵⁶ + + // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. + // This will give us the correct result modulo 2²⁵⁶. Since the preconditions guarantee that the outcome is + // less than 2²⁵⁶, this is the final result. We don't need to compute the high bits of the result and high + // is no longer required. + result = low * inverse; + return result; + } + } + + /** + * @dev Calculates x * y / denominator with full precision, following the selected rounding direction. + */ + function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { + return mulDiv(x, y, denominator) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0); + } + + /** + * @dev Calculates floor(x * y >> n) with full precision. Throws if result overflows a uint256. + */ + function mulShr(uint256 x, uint256 y, uint8 n) internal pure returns (uint256 result) { + unchecked { + (uint256 high, uint256 low) = mul512(x, y); + if (high >= 1 << n) { + Panic.panic(Panic.UNDER_OVERFLOW); + } + return (high << (256 - n)) | (low >> n); + } + } + + /** + * @dev Calculates x * y >> n with full precision, following the selected rounding direction. + */ + function mulShr(uint256 x, uint256 y, uint8 n, Rounding rounding) internal pure returns (uint256) { + return mulShr(x, y, n) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, 1 << n) > 0); + } + + /** + * @dev Calculate the modular multiplicative inverse of a number in Z/nZ. + * + * If n is a prime, then Z/nZ is a field. In that case all elements are inversible, except 0. + * If n is not a prime, then Z/nZ is not a field, and some elements might not be inversible. + * + * If the input value is not inversible, 0 is returned. + * + * NOTE: If you know for sure that n is (big) a prime, it may be cheaper to use Fermat's little theorem and get the + * inverse using `Math.modExp(a, n - 2, n)`. See {invModPrime}. + */ + function invMod(uint256 a, uint256 n) internal pure returns (uint256) { + unchecked { + if (n == 0) return 0; + + // The inverse modulo is calculated using the Extended Euclidean Algorithm (iterative version) + // Used to compute integers x and y such that: ax + ny = gcd(a, n). + // When the gcd is 1, then the inverse of a modulo n exists and it's x. + // ax + ny = 1 + // ax = 1 + (-y)n + // ax ≡ 1 (mod n) # x is the inverse of a modulo n + + // If the remainder is 0 the gcd is n right away. + uint256 remainder = a % n; + uint256 gcd = n; + + // Therefore the initial coefficients are: + // ax + ny = gcd(a, n) = n + // 0a + 1n = n + int256 x = 0; + int256 y = 1; + + while (remainder != 0) { + uint256 quotient = gcd / remainder; + + (gcd, remainder) = ( + // The old remainder is the next gcd to try. + remainder, + // Compute the next remainder. + // Can't overflow given that (a % gcd) * (gcd // (a % gcd)) <= gcd + // where gcd is at most n (capped to type(uint256).max) + gcd - remainder * quotient + ); + + (x, y) = ( + // Increment the coefficient of a. + y, + // Decrement the coefficient of n. + // Can overflow, but the result is casted to uint256 so that the + // next value of y is "wrapped around" to a value between 0 and n - 1. + x - y * int256(quotient) + ); + } + + if (gcd != 1) return 0; // No inverse exists. + return ternary(x < 0, n - uint256(-x), uint256(x)); // Wrap the result if it's negative. + } + } + + /** + * @dev Variant of {invMod}. More efficient, but only works if `p` is known to be a prime greater than `2`. + * + * From https://en.wikipedia.org/wiki/Fermat%27s_little_theorem[Fermat's little theorem], we know that if p is + * prime, then `a**(p-1) ≡ 1 mod p`. As a consequence, we have `a * a**(p-2) ≡ 1 mod p`, which means that + * `a**(p-2)` is the modular multiplicative inverse of a in Fp. + * + * NOTE: this function does NOT check that `p` is a prime greater than `2`. + */ + function invModPrime(uint256 a, uint256 p) internal view returns (uint256) { + unchecked { + return Math.modExp(a, p - 2, p); + } + } + + /** + * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m) + * + * Requirements: + * - modulus can't be zero + * - underlying staticcall to precompile must succeed + * + * IMPORTANT: The result is only valid if the underlying call succeeds. When using this function, make + * sure the chain you're using it on supports the precompiled contract for modular exponentiation + * at address 0x05 as specified in https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, + * the underlying function will succeed given the lack of a revert, but the result may be incorrectly + * interpreted as 0. + */ + function modExp(uint256 b, uint256 e, uint256 m) internal view returns (uint256) { + (bool success, uint256 result) = tryModExp(b, e, m); + if (!success) { + Panic.panic(Panic.DIVISION_BY_ZERO); + } + return result; + } + + /** + * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m). + * It includes a success flag indicating if the operation succeeded. Operation will be marked as failed if trying + * to operate modulo 0 or if the underlying precompile reverted. + * + * IMPORTANT: The result is only valid if the success flag is true. When using this function, make sure the chain + * you're using it on supports the precompiled contract for modular exponentiation at address 0x05 as specified in + * https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, the underlying function will succeed given the lack + * of a revert, but the result may be incorrectly interpreted as 0. + */ + function tryModExp(uint256 b, uint256 e, uint256 m) internal view returns (bool success, uint256 result) { + if (m == 0) return (false, 0); + assembly ("memory-safe") { + let ptr := mload(0x40) + // | Offset | Content | Content (Hex) | + // |-----------|------------|--------------------------------------------------------------------| + // | 0x00:0x1f | size of b | 0x0000000000000000000000000000000000000000000000000000000000000020 | + // | 0x20:0x3f | size of e | 0x0000000000000000000000000000000000000000000000000000000000000020 | + // | 0x40:0x5f | size of m | 0x0000000000000000000000000000000000000000000000000000000000000020 | + // | 0x60:0x7f | value of b | 0x<.............................................................b> | + // | 0x80:0x9f | value of e | 0x<.............................................................e> | + // | 0xa0:0xbf | value of m | 0x<.............................................................m> | + mstore(ptr, 0x20) + mstore(add(ptr, 0x20), 0x20) + mstore(add(ptr, 0x40), 0x20) + mstore(add(ptr, 0x60), b) + mstore(add(ptr, 0x80), e) + mstore(add(ptr, 0xa0), m) + + // Given the result < m, it's guaranteed to fit in 32 bytes, + // so we can use the memory scratch space located at offset 0. + success := staticcall(gas(), 0x05, ptr, 0xc0, 0x00, 0x20) + result := mload(0x00) + } + } + + /** + * @dev Variant of {modExp} that supports inputs of arbitrary length. + */ + function modExp(bytes memory b, bytes memory e, bytes memory m) internal view returns (bytes memory) { + (bool success, bytes memory result) = tryModExp(b, e, m); + if (!success) { + Panic.panic(Panic.DIVISION_BY_ZERO); + } + return result; + } + + /** + * @dev Variant of {tryModExp} that supports inputs of arbitrary length. + */ + function tryModExp( + bytes memory b, + bytes memory e, + bytes memory m + ) internal view returns (bool success, bytes memory result) { + if (_zeroBytes(m)) return (false, new bytes(0)); + + uint256 mLen = m.length; + + // Encode call args in result and move the free memory pointer + result = abi.encodePacked(b.length, e.length, mLen, b, e, m); + + assembly ("memory-safe") { + let dataPtr := add(result, 0x20) + // Write result on top of args to avoid allocating extra memory. + success := staticcall(gas(), 0x05, dataPtr, mload(result), dataPtr, mLen) + // Overwrite the length. + // result.length > returndatasize() is guaranteed because returndatasize() == m.length + mstore(result, mLen) + // Set the memory pointer after the returned data. + mstore(0x40, add(dataPtr, mLen)) + } + } + + /** + * @dev Returns whether the provided byte array is zero. + */ + function _zeroBytes(bytes memory byteArray) private pure returns (bool) { + for (uint256 i = 0; i < byteArray.length; ++i) { + if (byteArray[i] != 0) { + return false; + } + } + return true; + } + + /** + * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded + * towards zero. + * + * This method is based on Newton's method for computing square roots; the algorithm is restricted to only + * using integer operations. + */ + function sqrt(uint256 a) internal pure returns (uint256) { + unchecked { + // Take care of easy edge cases when a == 0 or a == 1 + if (a <= 1) { + return a; + } + + // In this function, we use Newton's method to get a root of `f(x) := x² - a`. It involves building a + // sequence x_n that converges toward sqrt(a). For each iteration x_n, we also define the error between + // the current value as `ε_n = | x_n - sqrt(a) |`. + // + // For our first estimation, we consider `e` the smallest power of 2 which is bigger than the square root + // of the target. (i.e. `2**(e-1) ≤ sqrt(a) < 2**e`). We know that `e ≤ 128` because `(2¹²⁸)² = 2²⁵⁶` is + // bigger than any uint256. + // + // By noticing that + // `2**(e-1) ≤ sqrt(a) < 2**e → (2**(e-1))² ≤ a < (2**e)² → 2**(2*e-2) ≤ a < 2**(2*e)` + // we can deduce that `e - 1` is `log2(a) / 2`. We can thus compute `x_n = 2**(e-1)` using a method similar + // to the msb function. + uint256 aa = a; + uint256 xn = 1; + + if (aa >= (1 << 128)) { + aa >>= 128; + xn <<= 64; + } + if (aa >= (1 << 64)) { + aa >>= 64; + xn <<= 32; + } + if (aa >= (1 << 32)) { + aa >>= 32; + xn <<= 16; + } + if (aa >= (1 << 16)) { + aa >>= 16; + xn <<= 8; + } + if (aa >= (1 << 8)) { + aa >>= 8; + xn <<= 4; + } + if (aa >= (1 << 4)) { + aa >>= 4; + xn <<= 2; + } + if (aa >= (1 << 2)) { + xn <<= 1; + } + + // We now have x_n such that `x_n = 2**(e-1) ≤ sqrt(a) < 2**e = 2 * x_n`. This implies ε_n ≤ 2**(e-1). + // + // We can refine our estimation by noticing that the middle of that interval minimizes the error. + // If we move x_n to equal 2**(e-1) + 2**(e-2), then we reduce the error to ε_n ≤ 2**(e-2). + // This is going to be our x_0 (and ε_0) + xn = (3 * xn) >> 1; // ε_0 := | x_0 - sqrt(a) | ≤ 2**(e-2) + + // From here, Newton's method give us: + // x_{n+1} = (x_n + a / x_n) / 2 + // + // One should note that: + // x_{n+1}² - a = ((x_n + a / x_n) / 2)² - a + // = ((x_n² + a) / (2 * x_n))² - a + // = (x_n⁴ + 2 * a * x_n² + a²) / (4 * x_n²) - a + // = (x_n⁴ + 2 * a * x_n² + a² - 4 * a * x_n²) / (4 * x_n²) + // = (x_n⁴ - 2 * a * x_n² + a²) / (4 * x_n²) + // = (x_n² - a)² / (2 * x_n)² + // = ((x_n² - a) / (2 * x_n))² + // ≥ 0 + // Which proves that for all n ≥ 1, sqrt(a) ≤ x_n + // + // This gives us the proof of quadratic convergence of the sequence: + // ε_{n+1} = | x_{n+1} - sqrt(a) | + // = | (x_n + a / x_n) / 2 - sqrt(a) | + // = | (x_n² + a - 2*x_n*sqrt(a)) / (2 * x_n) | + // = | (x_n - sqrt(a))² / (2 * x_n) | + // = | ε_n² / (2 * x_n) | + // = ε_n² / | (2 * x_n) | + // + // For the first iteration, we have a special case where x_0 is known: + // ε_1 = ε_0² / | (2 * x_0) | + // ≤ (2**(e-2))² / (2 * (2**(e-1) + 2**(e-2))) + // ≤ 2**(2*e-4) / (3 * 2**(e-1)) + // ≤ 2**(e-3) / 3 + // ≤ 2**(e-3-log2(3)) + // ≤ 2**(e-4.5) + // + // For the following iterations, we use the fact that, 2**(e-1) ≤ sqrt(a) ≤ x_n: + // ε_{n+1} = ε_n² / | (2 * x_n) | + // ≤ (2**(e-k))² / (2 * 2**(e-1)) + // ≤ 2**(2*e-2*k) / 2**e + // ≤ 2**(e-2*k) + xn = (xn + a / xn) >> 1; // ε_1 := | x_1 - sqrt(a) | ≤ 2**(e-4.5) -- special case, see above + xn = (xn + a / xn) >> 1; // ε_2 := | x_2 - sqrt(a) | ≤ 2**(e-9) -- general case with k = 4.5 + xn = (xn + a / xn) >> 1; // ε_3 := | x_3 - sqrt(a) | ≤ 2**(e-18) -- general case with k = 9 + xn = (xn + a / xn) >> 1; // ε_4 := | x_4 - sqrt(a) | ≤ 2**(e-36) -- general case with k = 18 + xn = (xn + a / xn) >> 1; // ε_5 := | x_5 - sqrt(a) | ≤ 2**(e-72) -- general case with k = 36 + xn = (xn + a / xn) >> 1; // ε_6 := | x_6 - sqrt(a) | ≤ 2**(e-144) -- general case with k = 72 + + // Because e ≤ 128 (as discussed during the first estimation phase), we know have reached a precision + // ε_6 ≤ 2**(e-144) < 1. Given we're operating on integers, then we can ensure that xn is now either + // sqrt(a) or sqrt(a) + 1. + return xn - SafeCast.toUint(xn > a / xn); + } + } + + /** + * @dev Calculates sqrt(a), following the selected rounding direction. + */ + function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { + unchecked { + uint256 result = sqrt(a); + return result + SafeCast.toUint(unsignedRoundsUp(rounding) && result * result < a); + } + } + + /** + * @dev Return the log in base 2 of a positive value rounded towards zero. + * Returns 0 if given 0. + */ + function log2(uint256 x) internal pure returns (uint256 r) { + // If value has upper 128 bits set, log2 result is at least 128 + r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7; + // If upper 64 bits of 128-bit half set, add 64 to result + r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6; + // If upper 32 bits of 64-bit half set, add 32 to result + r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5; + // If upper 16 bits of 32-bit half set, add 16 to result + r |= SafeCast.toUint((x >> r) > 0xffff) << 4; + // If upper 8 bits of 16-bit half set, add 8 to result + r |= SafeCast.toUint((x >> r) > 0xff) << 3; + // If upper 4 bits of 8-bit half set, add 4 to result + r |= SafeCast.toUint((x >> r) > 0xf) << 2; + + // Shifts value right by the current result and use it as an index into this lookup table: + // + // | x (4 bits) | index | table[index] = MSB position | + // |------------|---------|-----------------------------| + // | 0000 | 0 | table[0] = 0 | + // | 0001 | 1 | table[1] = 0 | + // | 0010 | 2 | table[2] = 1 | + // | 0011 | 3 | table[3] = 1 | + // | 0100 | 4 | table[4] = 2 | + // | 0101 | 5 | table[5] = 2 | + // | 0110 | 6 | table[6] = 2 | + // | 0111 | 7 | table[7] = 2 | + // | 1000 | 8 | table[8] = 3 | + // | 1001 | 9 | table[9] = 3 | + // | 1010 | 10 | table[10] = 3 | + // | 1011 | 11 | table[11] = 3 | + // | 1100 | 12 | table[12] = 3 | + // | 1101 | 13 | table[13] = 3 | + // | 1110 | 14 | table[14] = 3 | + // | 1111 | 15 | table[15] = 3 | + // + // The lookup table is represented as a 32-byte value with the MSB positions for 0-15 in the last 16 bytes. + assembly ("memory-safe") { + r := or(r, byte(shr(r, x), 0x0000010102020202030303030303030300000000000000000000000000000000)) + } + } + + /** + * @dev Return the log in base 2, following the selected rounding direction, of a positive value. + * Returns 0 if given 0. + */ + function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { + unchecked { + uint256 result = log2(value); + return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << result < value); + } + } + + /** + * @dev Return the log in base 10 of a positive value rounded towards zero. + * Returns 0 if given 0. + */ + function log10(uint256 value) internal pure returns (uint256) { + uint256 result = 0; + unchecked { + if (value >= 10 ** 64) { + value /= 10 ** 64; + result += 64; + } + if (value >= 10 ** 32) { + value /= 10 ** 32; + result += 32; + } + if (value >= 10 ** 16) { + value /= 10 ** 16; + result += 16; + } + if (value >= 10 ** 8) { + value /= 10 ** 8; + result += 8; + } + if (value >= 10 ** 4) { + value /= 10 ** 4; + result += 4; + } + if (value >= 10 ** 2) { + value /= 10 ** 2; + result += 2; + } + if (value >= 10 ** 1) { + result += 1; + } + } + return result; + } + + /** + * @dev Return the log in base 10, following the selected rounding direction, of a positive value. + * Returns 0 if given 0. + */ + function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { + unchecked { + uint256 result = log10(value); + return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 10 ** result < value); + } + } + + /** + * @dev Return the log in base 256 of a positive value rounded towards zero. + * Returns 0 if given 0. + * + * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. + */ + function log256(uint256 x) internal pure returns (uint256 r) { + // If value has upper 128 bits set, log2 result is at least 128 + r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7; + // If upper 64 bits of 128-bit half set, add 64 to result + r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6; + // If upper 32 bits of 64-bit half set, add 32 to result + r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5; + // If upper 16 bits of 32-bit half set, add 16 to result + r |= SafeCast.toUint((x >> r) > 0xffff) << 4; + // Add 1 if upper 8 bits of 16-bit half set, and divide accumulated result by 8 + return (r >> 3) | SafeCast.toUint((x >> r) > 0xff); + } + + /** + * @dev Return the log in base 256, following the selected rounding direction, of a positive value. + * Returns 0 if given 0. + */ + function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { + unchecked { + uint256 result = log256(value); + return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << (result << 3) < value); + } + } + + /** + * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers. + */ + function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) { + return uint8(rounding) % 2 == 1; + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/utils/math/SafeCast.sol b/dependencies/@openzeppelin-contracts-5.4.0/utils/math/SafeCast.sol new file mode 100644 index 00000000..b345ede1 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/utils/math/SafeCast.sol @@ -0,0 +1,1162 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SafeCast.sol) +// This file was procedurally generated from scripts/generate/templates/SafeCast.js. + +pragma solidity ^0.8.20; + +/** + * @dev Wrappers over Solidity's uintXX/intXX/bool casting operators with added overflow + * checks. + * + * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can + * easily result in undesired exploitation or bugs, since developers usually + * assume that overflows raise errors. `SafeCast` restores this intuition by + * reverting the transaction when such an operation overflows. + * + * Using this library instead of the unchecked operations eliminates an entire + * class of bugs, so it's recommended to use it always. + */ +library SafeCast { + /** + * @dev Value doesn't fit in an uint of `bits` size. + */ + error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value); + + /** + * @dev An int value doesn't fit in an uint of `bits` size. + */ + error SafeCastOverflowedIntToUint(int256 value); + + /** + * @dev Value doesn't fit in an int of `bits` size. + */ + error SafeCastOverflowedIntDowncast(uint8 bits, int256 value); + + /** + * @dev An uint value doesn't fit in an int of `bits` size. + */ + error SafeCastOverflowedUintToInt(uint256 value); + + /** + * @dev Returns the downcasted uint248 from uint256, reverting on + * overflow (when the input is greater than largest uint248). + * + * Counterpart to Solidity's `uint248` operator. + * + * Requirements: + * + * - input must fit into 248 bits + */ + function toUint248(uint256 value) internal pure returns (uint248) { + if (value > type(uint248).max) { + revert SafeCastOverflowedUintDowncast(248, value); + } + return uint248(value); + } + + /** + * @dev Returns the downcasted uint240 from uint256, reverting on + * overflow (when the input is greater than largest uint240). + * + * Counterpart to Solidity's `uint240` operator. + * + * Requirements: + * + * - input must fit into 240 bits + */ + function toUint240(uint256 value) internal pure returns (uint240) { + if (value > type(uint240).max) { + revert SafeCastOverflowedUintDowncast(240, value); + } + return uint240(value); + } + + /** + * @dev Returns the downcasted uint232 from uint256, reverting on + * overflow (when the input is greater than largest uint232). + * + * Counterpart to Solidity's `uint232` operator. + * + * Requirements: + * + * - input must fit into 232 bits + */ + function toUint232(uint256 value) internal pure returns (uint232) { + if (value > type(uint232).max) { + revert SafeCastOverflowedUintDowncast(232, value); + } + return uint232(value); + } + + /** + * @dev Returns the downcasted uint224 from uint256, reverting on + * overflow (when the input is greater than largest uint224). + * + * Counterpart to Solidity's `uint224` operator. + * + * Requirements: + * + * - input must fit into 224 bits + */ + function toUint224(uint256 value) internal pure returns (uint224) { + if (value > type(uint224).max) { + revert SafeCastOverflowedUintDowncast(224, value); + } + return uint224(value); + } + + /** + * @dev Returns the downcasted uint216 from uint256, reverting on + * overflow (when the input is greater than largest uint216). + * + * Counterpart to Solidity's `uint216` operator. + * + * Requirements: + * + * - input must fit into 216 bits + */ + function toUint216(uint256 value) internal pure returns (uint216) { + if (value > type(uint216).max) { + revert SafeCastOverflowedUintDowncast(216, value); + } + return uint216(value); + } + + /** + * @dev Returns the downcasted uint208 from uint256, reverting on + * overflow (when the input is greater than largest uint208). + * + * Counterpart to Solidity's `uint208` operator. + * + * Requirements: + * + * - input must fit into 208 bits + */ + function toUint208(uint256 value) internal pure returns (uint208) { + if (value > type(uint208).max) { + revert SafeCastOverflowedUintDowncast(208, value); + } + return uint208(value); + } + + /** + * @dev Returns the downcasted uint200 from uint256, reverting on + * overflow (when the input is greater than largest uint200). + * + * Counterpart to Solidity's `uint200` operator. + * + * Requirements: + * + * - input must fit into 200 bits + */ + function toUint200(uint256 value) internal pure returns (uint200) { + if (value > type(uint200).max) { + revert SafeCastOverflowedUintDowncast(200, value); + } + return uint200(value); + } + + /** + * @dev Returns the downcasted uint192 from uint256, reverting on + * overflow (when the input is greater than largest uint192). + * + * Counterpart to Solidity's `uint192` operator. + * + * Requirements: + * + * - input must fit into 192 bits + */ + function toUint192(uint256 value) internal pure returns (uint192) { + if (value > type(uint192).max) { + revert SafeCastOverflowedUintDowncast(192, value); + } + return uint192(value); + } + + /** + * @dev Returns the downcasted uint184 from uint256, reverting on + * overflow (when the input is greater than largest uint184). + * + * Counterpart to Solidity's `uint184` operator. + * + * Requirements: + * + * - input must fit into 184 bits + */ + function toUint184(uint256 value) internal pure returns (uint184) { + if (value > type(uint184).max) { + revert SafeCastOverflowedUintDowncast(184, value); + } + return uint184(value); + } + + /** + * @dev Returns the downcasted uint176 from uint256, reverting on + * overflow (when the input is greater than largest uint176). + * + * Counterpart to Solidity's `uint176` operator. + * + * Requirements: + * + * - input must fit into 176 bits + */ + function toUint176(uint256 value) internal pure returns (uint176) { + if (value > type(uint176).max) { + revert SafeCastOverflowedUintDowncast(176, value); + } + return uint176(value); + } + + /** + * @dev Returns the downcasted uint168 from uint256, reverting on + * overflow (when the input is greater than largest uint168). + * + * Counterpart to Solidity's `uint168` operator. + * + * Requirements: + * + * - input must fit into 168 bits + */ + function toUint168(uint256 value) internal pure returns (uint168) { + if (value > type(uint168).max) { + revert SafeCastOverflowedUintDowncast(168, value); + } + return uint168(value); + } + + /** + * @dev Returns the downcasted uint160 from uint256, reverting on + * overflow (when the input is greater than largest uint160). + * + * Counterpart to Solidity's `uint160` operator. + * + * Requirements: + * + * - input must fit into 160 bits + */ + function toUint160(uint256 value) internal pure returns (uint160) { + if (value > type(uint160).max) { + revert SafeCastOverflowedUintDowncast(160, value); + } + return uint160(value); + } + + /** + * @dev Returns the downcasted uint152 from uint256, reverting on + * overflow (when the input is greater than largest uint152). + * + * Counterpart to Solidity's `uint152` operator. + * + * Requirements: + * + * - input must fit into 152 bits + */ + function toUint152(uint256 value) internal pure returns (uint152) { + if (value > type(uint152).max) { + revert SafeCastOverflowedUintDowncast(152, value); + } + return uint152(value); + } + + /** + * @dev Returns the downcasted uint144 from uint256, reverting on + * overflow (when the input is greater than largest uint144). + * + * Counterpart to Solidity's `uint144` operator. + * + * Requirements: + * + * - input must fit into 144 bits + */ + function toUint144(uint256 value) internal pure returns (uint144) { + if (value > type(uint144).max) { + revert SafeCastOverflowedUintDowncast(144, value); + } + return uint144(value); + } + + /** + * @dev Returns the downcasted uint136 from uint256, reverting on + * overflow (when the input is greater than largest uint136). + * + * Counterpart to Solidity's `uint136` operator. + * + * Requirements: + * + * - input must fit into 136 bits + */ + function toUint136(uint256 value) internal pure returns (uint136) { + if (value > type(uint136).max) { + revert SafeCastOverflowedUintDowncast(136, value); + } + return uint136(value); + } + + /** + * @dev Returns the downcasted uint128 from uint256, reverting on + * overflow (when the input is greater than largest uint128). + * + * Counterpart to Solidity's `uint128` operator. + * + * Requirements: + * + * - input must fit into 128 bits + */ + function toUint128(uint256 value) internal pure returns (uint128) { + if (value > type(uint128).max) { + revert SafeCastOverflowedUintDowncast(128, value); + } + return uint128(value); + } + + /** + * @dev Returns the downcasted uint120 from uint256, reverting on + * overflow (when the input is greater than largest uint120). + * + * Counterpart to Solidity's `uint120` operator. + * + * Requirements: + * + * - input must fit into 120 bits + */ + function toUint120(uint256 value) internal pure returns (uint120) { + if (value > type(uint120).max) { + revert SafeCastOverflowedUintDowncast(120, value); + } + return uint120(value); + } + + /** + * @dev Returns the downcasted uint112 from uint256, reverting on + * overflow (when the input is greater than largest uint112). + * + * Counterpart to Solidity's `uint112` operator. + * + * Requirements: + * + * - input must fit into 112 bits + */ + function toUint112(uint256 value) internal pure returns (uint112) { + if (value > type(uint112).max) { + revert SafeCastOverflowedUintDowncast(112, value); + } + return uint112(value); + } + + /** + * @dev Returns the downcasted uint104 from uint256, reverting on + * overflow (when the input is greater than largest uint104). + * + * Counterpart to Solidity's `uint104` operator. + * + * Requirements: + * + * - input must fit into 104 bits + */ + function toUint104(uint256 value) internal pure returns (uint104) { + if (value > type(uint104).max) { + revert SafeCastOverflowedUintDowncast(104, value); + } + return uint104(value); + } + + /** + * @dev Returns the downcasted uint96 from uint256, reverting on + * overflow (when the input is greater than largest uint96). + * + * Counterpart to Solidity's `uint96` operator. + * + * Requirements: + * + * - input must fit into 96 bits + */ + function toUint96(uint256 value) internal pure returns (uint96) { + if (value > type(uint96).max) { + revert SafeCastOverflowedUintDowncast(96, value); + } + return uint96(value); + } + + /** + * @dev Returns the downcasted uint88 from uint256, reverting on + * overflow (when the input is greater than largest uint88). + * + * Counterpart to Solidity's `uint88` operator. + * + * Requirements: + * + * - input must fit into 88 bits + */ + function toUint88(uint256 value) internal pure returns (uint88) { + if (value > type(uint88).max) { + revert SafeCastOverflowedUintDowncast(88, value); + } + return uint88(value); + } + + /** + * @dev Returns the downcasted uint80 from uint256, reverting on + * overflow (when the input is greater than largest uint80). + * + * Counterpart to Solidity's `uint80` operator. + * + * Requirements: + * + * - input must fit into 80 bits + */ + function toUint80(uint256 value) internal pure returns (uint80) { + if (value > type(uint80).max) { + revert SafeCastOverflowedUintDowncast(80, value); + } + return uint80(value); + } + + /** + * @dev Returns the downcasted uint72 from uint256, reverting on + * overflow (when the input is greater than largest uint72). + * + * Counterpart to Solidity's `uint72` operator. + * + * Requirements: + * + * - input must fit into 72 bits + */ + function toUint72(uint256 value) internal pure returns (uint72) { + if (value > type(uint72).max) { + revert SafeCastOverflowedUintDowncast(72, value); + } + return uint72(value); + } + + /** + * @dev Returns the downcasted uint64 from uint256, reverting on + * overflow (when the input is greater than largest uint64). + * + * Counterpart to Solidity's `uint64` operator. + * + * Requirements: + * + * - input must fit into 64 bits + */ + function toUint64(uint256 value) internal pure returns (uint64) { + if (value > type(uint64).max) { + revert SafeCastOverflowedUintDowncast(64, value); + } + return uint64(value); + } + + /** + * @dev Returns the downcasted uint56 from uint256, reverting on + * overflow (when the input is greater than largest uint56). + * + * Counterpart to Solidity's `uint56` operator. + * + * Requirements: + * + * - input must fit into 56 bits + */ + function toUint56(uint256 value) internal pure returns (uint56) { + if (value > type(uint56).max) { + revert SafeCastOverflowedUintDowncast(56, value); + } + return uint56(value); + } + + /** + * @dev Returns the downcasted uint48 from uint256, reverting on + * overflow (when the input is greater than largest uint48). + * + * Counterpart to Solidity's `uint48` operator. + * + * Requirements: + * + * - input must fit into 48 bits + */ + function toUint48(uint256 value) internal pure returns (uint48) { + if (value > type(uint48).max) { + revert SafeCastOverflowedUintDowncast(48, value); + } + return uint48(value); + } + + /** + * @dev Returns the downcasted uint40 from uint256, reverting on + * overflow (when the input is greater than largest uint40). + * + * Counterpart to Solidity's `uint40` operator. + * + * Requirements: + * + * - input must fit into 40 bits + */ + function toUint40(uint256 value) internal pure returns (uint40) { + if (value > type(uint40).max) { + revert SafeCastOverflowedUintDowncast(40, value); + } + return uint40(value); + } + + /** + * @dev Returns the downcasted uint32 from uint256, reverting on + * overflow (when the input is greater than largest uint32). + * + * Counterpart to Solidity's `uint32` operator. + * + * Requirements: + * + * - input must fit into 32 bits + */ + function toUint32(uint256 value) internal pure returns (uint32) { + if (value > type(uint32).max) { + revert SafeCastOverflowedUintDowncast(32, value); + } + return uint32(value); + } + + /** + * @dev Returns the downcasted uint24 from uint256, reverting on + * overflow (when the input is greater than largest uint24). + * + * Counterpart to Solidity's `uint24` operator. + * + * Requirements: + * + * - input must fit into 24 bits + */ + function toUint24(uint256 value) internal pure returns (uint24) { + if (value > type(uint24).max) { + revert SafeCastOverflowedUintDowncast(24, value); + } + return uint24(value); + } + + /** + * @dev Returns the downcasted uint16 from uint256, reverting on + * overflow (when the input is greater than largest uint16). + * + * Counterpart to Solidity's `uint16` operator. + * + * Requirements: + * + * - input must fit into 16 bits + */ + function toUint16(uint256 value) internal pure returns (uint16) { + if (value > type(uint16).max) { + revert SafeCastOverflowedUintDowncast(16, value); + } + return uint16(value); + } + + /** + * @dev Returns the downcasted uint8 from uint256, reverting on + * overflow (when the input is greater than largest uint8). + * + * Counterpart to Solidity's `uint8` operator. + * + * Requirements: + * + * - input must fit into 8 bits + */ + function toUint8(uint256 value) internal pure returns (uint8) { + if (value > type(uint8).max) { + revert SafeCastOverflowedUintDowncast(8, value); + } + return uint8(value); + } + + /** + * @dev Converts a signed int256 into an unsigned uint256. + * + * Requirements: + * + * - input must be greater than or equal to 0. + */ + function toUint256(int256 value) internal pure returns (uint256) { + if (value < 0) { + revert SafeCastOverflowedIntToUint(value); + } + return uint256(value); + } + + /** + * @dev Returns the downcasted int248 from int256, reverting on + * overflow (when the input is less than smallest int248 or + * greater than largest int248). + * + * Counterpart to Solidity's `int248` operator. + * + * Requirements: + * + * - input must fit into 248 bits + */ + function toInt248(int256 value) internal pure returns (int248 downcasted) { + downcasted = int248(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(248, value); + } + } + + /** + * @dev Returns the downcasted int240 from int256, reverting on + * overflow (when the input is less than smallest int240 or + * greater than largest int240). + * + * Counterpart to Solidity's `int240` operator. + * + * Requirements: + * + * - input must fit into 240 bits + */ + function toInt240(int256 value) internal pure returns (int240 downcasted) { + downcasted = int240(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(240, value); + } + } + + /** + * @dev Returns the downcasted int232 from int256, reverting on + * overflow (when the input is less than smallest int232 or + * greater than largest int232). + * + * Counterpart to Solidity's `int232` operator. + * + * Requirements: + * + * - input must fit into 232 bits + */ + function toInt232(int256 value) internal pure returns (int232 downcasted) { + downcasted = int232(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(232, value); + } + } + + /** + * @dev Returns the downcasted int224 from int256, reverting on + * overflow (when the input is less than smallest int224 or + * greater than largest int224). + * + * Counterpart to Solidity's `int224` operator. + * + * Requirements: + * + * - input must fit into 224 bits + */ + function toInt224(int256 value) internal pure returns (int224 downcasted) { + downcasted = int224(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(224, value); + } + } + + /** + * @dev Returns the downcasted int216 from int256, reverting on + * overflow (when the input is less than smallest int216 or + * greater than largest int216). + * + * Counterpart to Solidity's `int216` operator. + * + * Requirements: + * + * - input must fit into 216 bits + */ + function toInt216(int256 value) internal pure returns (int216 downcasted) { + downcasted = int216(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(216, value); + } + } + + /** + * @dev Returns the downcasted int208 from int256, reverting on + * overflow (when the input is less than smallest int208 or + * greater than largest int208). + * + * Counterpart to Solidity's `int208` operator. + * + * Requirements: + * + * - input must fit into 208 bits + */ + function toInt208(int256 value) internal pure returns (int208 downcasted) { + downcasted = int208(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(208, value); + } + } + + /** + * @dev Returns the downcasted int200 from int256, reverting on + * overflow (when the input is less than smallest int200 or + * greater than largest int200). + * + * Counterpart to Solidity's `int200` operator. + * + * Requirements: + * + * - input must fit into 200 bits + */ + function toInt200(int256 value) internal pure returns (int200 downcasted) { + downcasted = int200(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(200, value); + } + } + + /** + * @dev Returns the downcasted int192 from int256, reverting on + * overflow (when the input is less than smallest int192 or + * greater than largest int192). + * + * Counterpart to Solidity's `int192` operator. + * + * Requirements: + * + * - input must fit into 192 bits + */ + function toInt192(int256 value) internal pure returns (int192 downcasted) { + downcasted = int192(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(192, value); + } + } + + /** + * @dev Returns the downcasted int184 from int256, reverting on + * overflow (when the input is less than smallest int184 or + * greater than largest int184). + * + * Counterpart to Solidity's `int184` operator. + * + * Requirements: + * + * - input must fit into 184 bits + */ + function toInt184(int256 value) internal pure returns (int184 downcasted) { + downcasted = int184(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(184, value); + } + } + + /** + * @dev Returns the downcasted int176 from int256, reverting on + * overflow (when the input is less than smallest int176 or + * greater than largest int176). + * + * Counterpart to Solidity's `int176` operator. + * + * Requirements: + * + * - input must fit into 176 bits + */ + function toInt176(int256 value) internal pure returns (int176 downcasted) { + downcasted = int176(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(176, value); + } + } + + /** + * @dev Returns the downcasted int168 from int256, reverting on + * overflow (when the input is less than smallest int168 or + * greater than largest int168). + * + * Counterpart to Solidity's `int168` operator. + * + * Requirements: + * + * - input must fit into 168 bits + */ + function toInt168(int256 value) internal pure returns (int168 downcasted) { + downcasted = int168(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(168, value); + } + } + + /** + * @dev Returns the downcasted int160 from int256, reverting on + * overflow (when the input is less than smallest int160 or + * greater than largest int160). + * + * Counterpart to Solidity's `int160` operator. + * + * Requirements: + * + * - input must fit into 160 bits + */ + function toInt160(int256 value) internal pure returns (int160 downcasted) { + downcasted = int160(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(160, value); + } + } + + /** + * @dev Returns the downcasted int152 from int256, reverting on + * overflow (when the input is less than smallest int152 or + * greater than largest int152). + * + * Counterpart to Solidity's `int152` operator. + * + * Requirements: + * + * - input must fit into 152 bits + */ + function toInt152(int256 value) internal pure returns (int152 downcasted) { + downcasted = int152(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(152, value); + } + } + + /** + * @dev Returns the downcasted int144 from int256, reverting on + * overflow (when the input is less than smallest int144 or + * greater than largest int144). + * + * Counterpart to Solidity's `int144` operator. + * + * Requirements: + * + * - input must fit into 144 bits + */ + function toInt144(int256 value) internal pure returns (int144 downcasted) { + downcasted = int144(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(144, value); + } + } + + /** + * @dev Returns the downcasted int136 from int256, reverting on + * overflow (when the input is less than smallest int136 or + * greater than largest int136). + * + * Counterpart to Solidity's `int136` operator. + * + * Requirements: + * + * - input must fit into 136 bits + */ + function toInt136(int256 value) internal pure returns (int136 downcasted) { + downcasted = int136(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(136, value); + } + } + + /** + * @dev Returns the downcasted int128 from int256, reverting on + * overflow (when the input is less than smallest int128 or + * greater than largest int128). + * + * Counterpart to Solidity's `int128` operator. + * + * Requirements: + * + * - input must fit into 128 bits + */ + function toInt128(int256 value) internal pure returns (int128 downcasted) { + downcasted = int128(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(128, value); + } + } + + /** + * @dev Returns the downcasted int120 from int256, reverting on + * overflow (when the input is less than smallest int120 or + * greater than largest int120). + * + * Counterpart to Solidity's `int120` operator. + * + * Requirements: + * + * - input must fit into 120 bits + */ + function toInt120(int256 value) internal pure returns (int120 downcasted) { + downcasted = int120(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(120, value); + } + } + + /** + * @dev Returns the downcasted int112 from int256, reverting on + * overflow (when the input is less than smallest int112 or + * greater than largest int112). + * + * Counterpart to Solidity's `int112` operator. + * + * Requirements: + * + * - input must fit into 112 bits + */ + function toInt112(int256 value) internal pure returns (int112 downcasted) { + downcasted = int112(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(112, value); + } + } + + /** + * @dev Returns the downcasted int104 from int256, reverting on + * overflow (when the input is less than smallest int104 or + * greater than largest int104). + * + * Counterpart to Solidity's `int104` operator. + * + * Requirements: + * + * - input must fit into 104 bits + */ + function toInt104(int256 value) internal pure returns (int104 downcasted) { + downcasted = int104(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(104, value); + } + } + + /** + * @dev Returns the downcasted int96 from int256, reverting on + * overflow (when the input is less than smallest int96 or + * greater than largest int96). + * + * Counterpart to Solidity's `int96` operator. + * + * Requirements: + * + * - input must fit into 96 bits + */ + function toInt96(int256 value) internal pure returns (int96 downcasted) { + downcasted = int96(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(96, value); + } + } + + /** + * @dev Returns the downcasted int88 from int256, reverting on + * overflow (when the input is less than smallest int88 or + * greater than largest int88). + * + * Counterpart to Solidity's `int88` operator. + * + * Requirements: + * + * - input must fit into 88 bits + */ + function toInt88(int256 value) internal pure returns (int88 downcasted) { + downcasted = int88(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(88, value); + } + } + + /** + * @dev Returns the downcasted int80 from int256, reverting on + * overflow (when the input is less than smallest int80 or + * greater than largest int80). + * + * Counterpart to Solidity's `int80` operator. + * + * Requirements: + * + * - input must fit into 80 bits + */ + function toInt80(int256 value) internal pure returns (int80 downcasted) { + downcasted = int80(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(80, value); + } + } + + /** + * @dev Returns the downcasted int72 from int256, reverting on + * overflow (when the input is less than smallest int72 or + * greater than largest int72). + * + * Counterpart to Solidity's `int72` operator. + * + * Requirements: + * + * - input must fit into 72 bits + */ + function toInt72(int256 value) internal pure returns (int72 downcasted) { + downcasted = int72(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(72, value); + } + } + + /** + * @dev Returns the downcasted int64 from int256, reverting on + * overflow (when the input is less than smallest int64 or + * greater than largest int64). + * + * Counterpart to Solidity's `int64` operator. + * + * Requirements: + * + * - input must fit into 64 bits + */ + function toInt64(int256 value) internal pure returns (int64 downcasted) { + downcasted = int64(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(64, value); + } + } + + /** + * @dev Returns the downcasted int56 from int256, reverting on + * overflow (when the input is less than smallest int56 or + * greater than largest int56). + * + * Counterpart to Solidity's `int56` operator. + * + * Requirements: + * + * - input must fit into 56 bits + */ + function toInt56(int256 value) internal pure returns (int56 downcasted) { + downcasted = int56(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(56, value); + } + } + + /** + * @dev Returns the downcasted int48 from int256, reverting on + * overflow (when the input is less than smallest int48 or + * greater than largest int48). + * + * Counterpart to Solidity's `int48` operator. + * + * Requirements: + * + * - input must fit into 48 bits + */ + function toInt48(int256 value) internal pure returns (int48 downcasted) { + downcasted = int48(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(48, value); + } + } + + /** + * @dev Returns the downcasted int40 from int256, reverting on + * overflow (when the input is less than smallest int40 or + * greater than largest int40). + * + * Counterpart to Solidity's `int40` operator. + * + * Requirements: + * + * - input must fit into 40 bits + */ + function toInt40(int256 value) internal pure returns (int40 downcasted) { + downcasted = int40(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(40, value); + } + } + + /** + * @dev Returns the downcasted int32 from int256, reverting on + * overflow (when the input is less than smallest int32 or + * greater than largest int32). + * + * Counterpart to Solidity's `int32` operator. + * + * Requirements: + * + * - input must fit into 32 bits + */ + function toInt32(int256 value) internal pure returns (int32 downcasted) { + downcasted = int32(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(32, value); + } + } + + /** + * @dev Returns the downcasted int24 from int256, reverting on + * overflow (when the input is less than smallest int24 or + * greater than largest int24). + * + * Counterpart to Solidity's `int24` operator. + * + * Requirements: + * + * - input must fit into 24 bits + */ + function toInt24(int256 value) internal pure returns (int24 downcasted) { + downcasted = int24(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(24, value); + } + } + + /** + * @dev Returns the downcasted int16 from int256, reverting on + * overflow (when the input is less than smallest int16 or + * greater than largest int16). + * + * Counterpart to Solidity's `int16` operator. + * + * Requirements: + * + * - input must fit into 16 bits + */ + function toInt16(int256 value) internal pure returns (int16 downcasted) { + downcasted = int16(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(16, value); + } + } + + /** + * @dev Returns the downcasted int8 from int256, reverting on + * overflow (when the input is less than smallest int8 or + * greater than largest int8). + * + * Counterpart to Solidity's `int8` operator. + * + * Requirements: + * + * - input must fit into 8 bits + */ + function toInt8(int256 value) internal pure returns (int8 downcasted) { + downcasted = int8(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(8, value); + } + } + + /** + * @dev Converts an unsigned uint256 into a signed int256. + * + * Requirements: + * + * - input must be less than or equal to maxInt256. + */ + function toInt256(uint256 value) internal pure returns (int256) { + // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive + if (value > uint256(type(int256).max)) { + revert SafeCastOverflowedUintToInt(value); + } + return int256(value); + } + + /** + * @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump. + */ + function toUint(bool b) internal pure returns (uint256 u) { + assembly ("memory-safe") { + u := iszero(iszero(b)) + } + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/utils/math/SignedMath.sol b/dependencies/@openzeppelin-contracts-5.4.0/utils/math/SignedMath.sol new file mode 100644 index 00000000..7c97aa4c --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/utils/math/SignedMath.sol @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SignedMath.sol) + +pragma solidity ^0.8.20; + +import {SafeCast} from "./SafeCast.sol"; + +/** + * @dev Standard signed math utilities missing in the Solidity language. + */ +library SignedMath { + /** + * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant. + * + * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone. + * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute + * one branch when needed, making this function more expensive. + */ + function ternary(bool condition, int256 a, int256 b) internal pure returns (int256) { + unchecked { + // branchless ternary works because: + // b ^ (a ^ b) == a + // b ^ 0 == b + return b ^ ((a ^ b) * int256(SafeCast.toUint(condition))); + } + } + + /** + * @dev Returns the largest of two signed numbers. + */ + function max(int256 a, int256 b) internal pure returns (int256) { + return ternary(a > b, a, b); + } + + /** + * @dev Returns the smallest of two signed numbers. + */ + function min(int256 a, int256 b) internal pure returns (int256) { + return ternary(a < b, a, b); + } + + /** + * @dev Returns the average of two signed numbers without overflow. + * The result is rounded towards zero. + */ + function average(int256 a, int256 b) internal pure returns (int256) { + // Formula from the book "Hacker's Delight" + int256 x = (a & b) + ((a ^ b) >> 1); + return x + (int256(uint256(x) >> 255) & (a ^ b)); + } + + /** + * @dev Returns the absolute unsigned value of a signed value. + */ + function abs(int256 n) internal pure returns (uint256) { + unchecked { + // Formula from the "Bit Twiddling Hacks" by Sean Eron Anderson. + // Since `n` is a signed integer, the generated bytecode will use the SAR opcode to perform the right shift, + // taking advantage of the most significant (or "sign" bit) in two's complement representation. + // This opcode adds new most significant bits set to the value of the previous most significant bit. As a result, + // the mask will either be `bytes32(0)` (if n is positive) or `~bytes32(0)` (if n is negative). + int256 mask = n >> 255; + + // A `bytes32(0)` mask leaves the input unchanged, while a `~bytes32(0)` mask complements it. + return uint256((n + mask) ^ mask); + } + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/utils/structs/BitMaps.sol b/dependencies/@openzeppelin-contracts-5.4.0/utils/structs/BitMaps.sol new file mode 100644 index 00000000..40cceb90 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/utils/structs/BitMaps.sol @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/BitMaps.sol) +pragma solidity ^0.8.20; + +/** + * @dev Library for managing uint256 to bool mapping in a compact and efficient way, provided the keys are sequential. + * Largely inspired by Uniswap's https://github.com/Uniswap/merkle-distributor/blob/master/contracts/MerkleDistributor.sol[merkle-distributor]. + * + * BitMaps pack 256 booleans across each bit of a single 256-bit slot of `uint256` type. + * Hence booleans corresponding to 256 _sequential_ indices would only consume a single slot, + * unlike the regular `bool` which would consume an entire slot for a single value. + * + * This results in gas savings in two ways: + * + * - Setting a zero value to non-zero only once every 256 times + * - Accessing the same warm slot for every 256 _sequential_ indices + */ +library BitMaps { + struct BitMap { + mapping(uint256 bucket => uint256) _data; + } + + /** + * @dev Returns whether the bit at `index` is set. + */ + function get(BitMap storage bitmap, uint256 index) internal view returns (bool) { + uint256 bucket = index >> 8; + uint256 mask = 1 << (index & 0xff); + return bitmap._data[bucket] & mask != 0; + } + + /** + * @dev Sets the bit at `index` to the boolean `value`. + */ + function setTo(BitMap storage bitmap, uint256 index, bool value) internal { + if (value) { + set(bitmap, index); + } else { + unset(bitmap, index); + } + } + + /** + * @dev Sets the bit at `index`. + */ + function set(BitMap storage bitmap, uint256 index) internal { + uint256 bucket = index >> 8; + uint256 mask = 1 << (index & 0xff); + bitmap._data[bucket] |= mask; + } + + /** + * @dev Unsets the bit at `index`. + */ + function unset(BitMap storage bitmap, uint256 index) internal { + uint256 bucket = index >> 8; + uint256 mask = 1 << (index & 0xff); + bitmap._data[bucket] &= ~mask; + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/utils/structs/Checkpoints.sol b/dependencies/@openzeppelin-contracts-5.4.0/utils/structs/Checkpoints.sol new file mode 100644 index 00000000..ce88f51d --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/utils/structs/Checkpoints.sol @@ -0,0 +1,630 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (utils/structs/Checkpoints.sol) +// This file was procedurally generated from scripts/generate/templates/Checkpoints.js. + +pragma solidity ^0.8.20; + +import {Math} from "../math/Math.sol"; + +/** + * @dev This library defines the `Trace*` struct, for checkpointing values as they change at different points in + * time, and later looking up past values by block number. See {Votes} as an example. + * + * To create a history of checkpoints define a variable type `Checkpoints.Trace*` in your contract, and store a new + * checkpoint for the current transaction block using the {push} function. + */ +library Checkpoints { + /** + * @dev A value was attempted to be inserted on a past checkpoint. + */ + error CheckpointUnorderedInsertion(); + + struct Trace224 { + Checkpoint224[] _checkpoints; + } + + struct Checkpoint224 { + uint32 _key; + uint224 _value; + } + + /** + * @dev Pushes a (`key`, `value`) pair into a Trace224 so that it is stored as the checkpoint. + * + * Returns previous value and new value. + * + * IMPORTANT: Never accept `key` as a user input, since an arbitrary `type(uint32).max` key set will disable the + * library. + */ + function push( + Trace224 storage self, + uint32 key, + uint224 value + ) internal returns (uint224 oldValue, uint224 newValue) { + return _insert(self._checkpoints, key, value); + } + + /** + * @dev Returns the value in the first (oldest) checkpoint with key greater or equal than the search key, or zero if + * there is none. + */ + function lowerLookup(Trace224 storage self, uint32 key) internal view returns (uint224) { + uint256 len = self._checkpoints.length; + uint256 pos = _lowerBinaryLookup(self._checkpoints, key, 0, len); + return pos == len ? 0 : _unsafeAccess(self._checkpoints, pos)._value; + } + + /** + * @dev Returns the value in the last (most recent) checkpoint with key lower or equal than the search key, or zero + * if there is none. + */ + function upperLookup(Trace224 storage self, uint32 key) internal view returns (uint224) { + uint256 len = self._checkpoints.length; + uint256 pos = _upperBinaryLookup(self._checkpoints, key, 0, len); + return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value; + } + + /** + * @dev Returns the value in the last (most recent) checkpoint with key lower or equal than the search key, or zero + * if there is none. + * + * NOTE: This is a variant of {upperLookup} that is optimized to find "recent" checkpoint (checkpoints with high + * keys). + */ + function upperLookupRecent(Trace224 storage self, uint32 key) internal view returns (uint224) { + uint256 len = self._checkpoints.length; + + uint256 low = 0; + uint256 high = len; + + if (len > 5) { + uint256 mid = len - Math.sqrt(len); + if (key < _unsafeAccess(self._checkpoints, mid)._key) { + high = mid; + } else { + low = mid + 1; + } + } + + uint256 pos = _upperBinaryLookup(self._checkpoints, key, low, high); + + return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value; + } + + /** + * @dev Returns the value in the most recent checkpoint, or zero if there are no checkpoints. + */ + function latest(Trace224 storage self) internal view returns (uint224) { + uint256 pos = self._checkpoints.length; + return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value; + } + + /** + * @dev Returns whether there is a checkpoint in the structure (i.e. it is not empty), and if so the key and value + * in the most recent checkpoint. + */ + function latestCheckpoint(Trace224 storage self) internal view returns (bool exists, uint32 _key, uint224 _value) { + uint256 pos = self._checkpoints.length; + if (pos == 0) { + return (false, 0, 0); + } else { + Checkpoint224 storage ckpt = _unsafeAccess(self._checkpoints, pos - 1); + return (true, ckpt._key, ckpt._value); + } + } + + /** + * @dev Returns the number of checkpoints. + */ + function length(Trace224 storage self) internal view returns (uint256) { + return self._checkpoints.length; + } + + /** + * @dev Returns checkpoint at given position. + */ + function at(Trace224 storage self, uint32 pos) internal view returns (Checkpoint224 memory) { + return self._checkpoints[pos]; + } + + /** + * @dev Pushes a (`key`, `value`) pair into an ordered list of checkpoints, either by inserting a new checkpoint, + * or by updating the last one. + */ + function _insert( + Checkpoint224[] storage self, + uint32 key, + uint224 value + ) private returns (uint224 oldValue, uint224 newValue) { + uint256 pos = self.length; + + if (pos > 0) { + Checkpoint224 storage last = _unsafeAccess(self, pos - 1); + uint32 lastKey = last._key; + uint224 lastValue = last._value; + + // Checkpoint keys must be non-decreasing. + if (lastKey > key) { + revert CheckpointUnorderedInsertion(); + } + + // Update or push new checkpoint + if (lastKey == key) { + last._value = value; + } else { + self.push(Checkpoint224({_key: key, _value: value})); + } + return (lastValue, value); + } else { + self.push(Checkpoint224({_key: key, _value: value})); + return (0, value); + } + } + + /** + * @dev Return the index of the first (oldest) checkpoint with key strictly bigger than the search key, or `high` + * if there is none. `low` and `high` define a section where to do the search, with inclusive `low` and exclusive + * `high`. + * + * WARNING: `high` should not be greater than the array's length. + */ + function _upperBinaryLookup( + Checkpoint224[] storage self, + uint32 key, + uint256 low, + uint256 high + ) private view returns (uint256) { + while (low < high) { + uint256 mid = Math.average(low, high); + if (_unsafeAccess(self, mid)._key > key) { + high = mid; + } else { + low = mid + 1; + } + } + return high; + } + + /** + * @dev Return the index of the first (oldest) checkpoint with key greater or equal than the search key, or `high` + * if there is none. `low` and `high` define a section where to do the search, with inclusive `low` and exclusive + * `high`. + * + * WARNING: `high` should not be greater than the array's length. + */ + function _lowerBinaryLookup( + Checkpoint224[] storage self, + uint32 key, + uint256 low, + uint256 high + ) private view returns (uint256) { + while (low < high) { + uint256 mid = Math.average(low, high); + if (_unsafeAccess(self, mid)._key < key) { + low = mid + 1; + } else { + high = mid; + } + } + return high; + } + + /** + * @dev Access an element of the array without performing bounds check. The position is assumed to be within bounds. + */ + function _unsafeAccess( + Checkpoint224[] storage self, + uint256 pos + ) private pure returns (Checkpoint224 storage result) { + assembly { + mstore(0, self.slot) + result.slot := add(keccak256(0, 0x20), pos) + } + } + + struct Trace208 { + Checkpoint208[] _checkpoints; + } + + struct Checkpoint208 { + uint48 _key; + uint208 _value; + } + + /** + * @dev Pushes a (`key`, `value`) pair into a Trace208 so that it is stored as the checkpoint. + * + * Returns previous value and new value. + * + * IMPORTANT: Never accept `key` as a user input, since an arbitrary `type(uint48).max` key set will disable the + * library. + */ + function push( + Trace208 storage self, + uint48 key, + uint208 value + ) internal returns (uint208 oldValue, uint208 newValue) { + return _insert(self._checkpoints, key, value); + } + + /** + * @dev Returns the value in the first (oldest) checkpoint with key greater or equal than the search key, or zero if + * there is none. + */ + function lowerLookup(Trace208 storage self, uint48 key) internal view returns (uint208) { + uint256 len = self._checkpoints.length; + uint256 pos = _lowerBinaryLookup(self._checkpoints, key, 0, len); + return pos == len ? 0 : _unsafeAccess(self._checkpoints, pos)._value; + } + + /** + * @dev Returns the value in the last (most recent) checkpoint with key lower or equal than the search key, or zero + * if there is none. + */ + function upperLookup(Trace208 storage self, uint48 key) internal view returns (uint208) { + uint256 len = self._checkpoints.length; + uint256 pos = _upperBinaryLookup(self._checkpoints, key, 0, len); + return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value; + } + + /** + * @dev Returns the value in the last (most recent) checkpoint with key lower or equal than the search key, or zero + * if there is none. + * + * NOTE: This is a variant of {upperLookup} that is optimized to find "recent" checkpoint (checkpoints with high + * keys). + */ + function upperLookupRecent(Trace208 storage self, uint48 key) internal view returns (uint208) { + uint256 len = self._checkpoints.length; + + uint256 low = 0; + uint256 high = len; + + if (len > 5) { + uint256 mid = len - Math.sqrt(len); + if (key < _unsafeAccess(self._checkpoints, mid)._key) { + high = mid; + } else { + low = mid + 1; + } + } + + uint256 pos = _upperBinaryLookup(self._checkpoints, key, low, high); + + return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value; + } + + /** + * @dev Returns the value in the most recent checkpoint, or zero if there are no checkpoints. + */ + function latest(Trace208 storage self) internal view returns (uint208) { + uint256 pos = self._checkpoints.length; + return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value; + } + + /** + * @dev Returns whether there is a checkpoint in the structure (i.e. it is not empty), and if so the key and value + * in the most recent checkpoint. + */ + function latestCheckpoint(Trace208 storage self) internal view returns (bool exists, uint48 _key, uint208 _value) { + uint256 pos = self._checkpoints.length; + if (pos == 0) { + return (false, 0, 0); + } else { + Checkpoint208 storage ckpt = _unsafeAccess(self._checkpoints, pos - 1); + return (true, ckpt._key, ckpt._value); + } + } + + /** + * @dev Returns the number of checkpoints. + */ + function length(Trace208 storage self) internal view returns (uint256) { + return self._checkpoints.length; + } + + /** + * @dev Returns checkpoint at given position. + */ + function at(Trace208 storage self, uint32 pos) internal view returns (Checkpoint208 memory) { + return self._checkpoints[pos]; + } + + /** + * @dev Pushes a (`key`, `value`) pair into an ordered list of checkpoints, either by inserting a new checkpoint, + * or by updating the last one. + */ + function _insert( + Checkpoint208[] storage self, + uint48 key, + uint208 value + ) private returns (uint208 oldValue, uint208 newValue) { + uint256 pos = self.length; + + if (pos > 0) { + Checkpoint208 storage last = _unsafeAccess(self, pos - 1); + uint48 lastKey = last._key; + uint208 lastValue = last._value; + + // Checkpoint keys must be non-decreasing. + if (lastKey > key) { + revert CheckpointUnorderedInsertion(); + } + + // Update or push new checkpoint + if (lastKey == key) { + last._value = value; + } else { + self.push(Checkpoint208({_key: key, _value: value})); + } + return (lastValue, value); + } else { + self.push(Checkpoint208({_key: key, _value: value})); + return (0, value); + } + } + + /** + * @dev Return the index of the first (oldest) checkpoint with key strictly bigger than the search key, or `high` + * if there is none. `low` and `high` define a section where to do the search, with inclusive `low` and exclusive + * `high`. + * + * WARNING: `high` should not be greater than the array's length. + */ + function _upperBinaryLookup( + Checkpoint208[] storage self, + uint48 key, + uint256 low, + uint256 high + ) private view returns (uint256) { + while (low < high) { + uint256 mid = Math.average(low, high); + if (_unsafeAccess(self, mid)._key > key) { + high = mid; + } else { + low = mid + 1; + } + } + return high; + } + + /** + * @dev Return the index of the first (oldest) checkpoint with key greater or equal than the search key, or `high` + * if there is none. `low` and `high` define a section where to do the search, with inclusive `low` and exclusive + * `high`. + * + * WARNING: `high` should not be greater than the array's length. + */ + function _lowerBinaryLookup( + Checkpoint208[] storage self, + uint48 key, + uint256 low, + uint256 high + ) private view returns (uint256) { + while (low < high) { + uint256 mid = Math.average(low, high); + if (_unsafeAccess(self, mid)._key < key) { + low = mid + 1; + } else { + high = mid; + } + } + return high; + } + + /** + * @dev Access an element of the array without performing bounds check. The position is assumed to be within bounds. + */ + function _unsafeAccess( + Checkpoint208[] storage self, + uint256 pos + ) private pure returns (Checkpoint208 storage result) { + assembly { + mstore(0, self.slot) + result.slot := add(keccak256(0, 0x20), pos) + } + } + + struct Trace160 { + Checkpoint160[] _checkpoints; + } + + struct Checkpoint160 { + uint96 _key; + uint160 _value; + } + + /** + * @dev Pushes a (`key`, `value`) pair into a Trace160 so that it is stored as the checkpoint. + * + * Returns previous value and new value. + * + * IMPORTANT: Never accept `key` as a user input, since an arbitrary `type(uint96).max` key set will disable the + * library. + */ + function push( + Trace160 storage self, + uint96 key, + uint160 value + ) internal returns (uint160 oldValue, uint160 newValue) { + return _insert(self._checkpoints, key, value); + } + + /** + * @dev Returns the value in the first (oldest) checkpoint with key greater or equal than the search key, or zero if + * there is none. + */ + function lowerLookup(Trace160 storage self, uint96 key) internal view returns (uint160) { + uint256 len = self._checkpoints.length; + uint256 pos = _lowerBinaryLookup(self._checkpoints, key, 0, len); + return pos == len ? 0 : _unsafeAccess(self._checkpoints, pos)._value; + } + + /** + * @dev Returns the value in the last (most recent) checkpoint with key lower or equal than the search key, or zero + * if there is none. + */ + function upperLookup(Trace160 storage self, uint96 key) internal view returns (uint160) { + uint256 len = self._checkpoints.length; + uint256 pos = _upperBinaryLookup(self._checkpoints, key, 0, len); + return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value; + } + + /** + * @dev Returns the value in the last (most recent) checkpoint with key lower or equal than the search key, or zero + * if there is none. + * + * NOTE: This is a variant of {upperLookup} that is optimized to find "recent" checkpoint (checkpoints with high + * keys). + */ + function upperLookupRecent(Trace160 storage self, uint96 key) internal view returns (uint160) { + uint256 len = self._checkpoints.length; + + uint256 low = 0; + uint256 high = len; + + if (len > 5) { + uint256 mid = len - Math.sqrt(len); + if (key < _unsafeAccess(self._checkpoints, mid)._key) { + high = mid; + } else { + low = mid + 1; + } + } + + uint256 pos = _upperBinaryLookup(self._checkpoints, key, low, high); + + return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value; + } + + /** + * @dev Returns the value in the most recent checkpoint, or zero if there are no checkpoints. + */ + function latest(Trace160 storage self) internal view returns (uint160) { + uint256 pos = self._checkpoints.length; + return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value; + } + + /** + * @dev Returns whether there is a checkpoint in the structure (i.e. it is not empty), and if so the key and value + * in the most recent checkpoint. + */ + function latestCheckpoint(Trace160 storage self) internal view returns (bool exists, uint96 _key, uint160 _value) { + uint256 pos = self._checkpoints.length; + if (pos == 0) { + return (false, 0, 0); + } else { + Checkpoint160 storage ckpt = _unsafeAccess(self._checkpoints, pos - 1); + return (true, ckpt._key, ckpt._value); + } + } + + /** + * @dev Returns the number of checkpoints. + */ + function length(Trace160 storage self) internal view returns (uint256) { + return self._checkpoints.length; + } + + /** + * @dev Returns checkpoint at given position. + */ + function at(Trace160 storage self, uint32 pos) internal view returns (Checkpoint160 memory) { + return self._checkpoints[pos]; + } + + /** + * @dev Pushes a (`key`, `value`) pair into an ordered list of checkpoints, either by inserting a new checkpoint, + * or by updating the last one. + */ + function _insert( + Checkpoint160[] storage self, + uint96 key, + uint160 value + ) private returns (uint160 oldValue, uint160 newValue) { + uint256 pos = self.length; + + if (pos > 0) { + Checkpoint160 storage last = _unsafeAccess(self, pos - 1); + uint96 lastKey = last._key; + uint160 lastValue = last._value; + + // Checkpoint keys must be non-decreasing. + if (lastKey > key) { + revert CheckpointUnorderedInsertion(); + } + + // Update or push new checkpoint + if (lastKey == key) { + last._value = value; + } else { + self.push(Checkpoint160({_key: key, _value: value})); + } + return (lastValue, value); + } else { + self.push(Checkpoint160({_key: key, _value: value})); + return (0, value); + } + } + + /** + * @dev Return the index of the first (oldest) checkpoint with key strictly bigger than the search key, or `high` + * if there is none. `low` and `high` define a section where to do the search, with inclusive `low` and exclusive + * `high`. + * + * WARNING: `high` should not be greater than the array's length. + */ + function _upperBinaryLookup( + Checkpoint160[] storage self, + uint96 key, + uint256 low, + uint256 high + ) private view returns (uint256) { + while (low < high) { + uint256 mid = Math.average(low, high); + if (_unsafeAccess(self, mid)._key > key) { + high = mid; + } else { + low = mid + 1; + } + } + return high; + } + + /** + * @dev Return the index of the first (oldest) checkpoint with key greater or equal than the search key, or `high` + * if there is none. `low` and `high` define a section where to do the search, with inclusive `low` and exclusive + * `high`. + * + * WARNING: `high` should not be greater than the array's length. + */ + function _lowerBinaryLookup( + Checkpoint160[] storage self, + uint96 key, + uint256 low, + uint256 high + ) private view returns (uint256) { + while (low < high) { + uint256 mid = Math.average(low, high); + if (_unsafeAccess(self, mid)._key < key) { + low = mid + 1; + } else { + high = mid; + } + } + return high; + } + + /** + * @dev Access an element of the array without performing bounds check. The position is assumed to be within bounds. + */ + function _unsafeAccess( + Checkpoint160[] storage self, + uint256 pos + ) private pure returns (Checkpoint160 storage result) { + assembly { + mstore(0, self.slot) + result.slot := add(keccak256(0, 0x20), pos) + } + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/utils/structs/CircularBuffer.sol b/dependencies/@openzeppelin-contracts-5.4.0/utils/structs/CircularBuffer.sol new file mode 100644 index 00000000..43ce89be --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/utils/structs/CircularBuffer.sol @@ -0,0 +1,140 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.3.0) (utils/structs/CircularBuffer.sol) +pragma solidity ^0.8.20; + +import {Math} from "../math/Math.sol"; +import {Arrays} from "../Arrays.sol"; +import {Panic} from "../Panic.sol"; + +/** + * @dev A fixed-size buffer for keeping `bytes32` items in storage. + * + * This data structure allows for pushing elements to it, and when its length exceeds the specified fixed size, + * new items take the place of the oldest element in the buffer, keeping at most `N` elements in the + * structure. + * + * Elements can't be removed but the data structure can be cleared. See {clear}. + * + * Complexity: + * - insertion ({push}): O(1) + * - lookup ({last}): O(1) + * - inclusion ({includes}): O(N) (worst case) + * - reset ({clear}): O(1) + * + * * The struct is called `Bytes32CircularBuffer`. Other types can be cast to and from `bytes32`. This data structure + * can only be used in storage, and not in memory. + * + * Example usage: + * + * ```solidity + * contract Example { + * // Add the library methods + * using CircularBuffer for CircularBuffer.Bytes32CircularBuffer; + * + * // Declare a buffer storage variable + * CircularBuffer.Bytes32CircularBuffer private myBuffer; + * } + * ``` + * + * _Available since v5.1._ + */ +library CircularBuffer { + /** + * @dev Error emitted when trying to setup a buffer with a size of 0. + */ + error InvalidBufferSize(); + + /** + * @dev Counts the number of items that have been pushed to the buffer. The residuo modulo _data.length indicates + * where the next value should be stored. + * + * Struct members have an underscore prefix indicating that they are "private" and should not be read or written to + * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and + * lead to unexpected behavior. + * + * In a full buffer: + * - The most recently pushed item (last) is at data[(index - 1) % data.length] + * - The oldest item (first) is at data[index % data.length] + */ + struct Bytes32CircularBuffer { + uint256 _count; + bytes32[] _data; + } + + /** + * @dev Initialize a new CircularBuffer of a given size. + * + * If the CircularBuffer was already setup and used, calling that function again will reset it to a blank state. + * + * NOTE: The size of the buffer will affect the execution of {includes} function, as it has a complexity of O(N). + * Consider a large buffer size may render the function unusable. + */ + function setup(Bytes32CircularBuffer storage self, uint256 size) internal { + if (size == 0) revert InvalidBufferSize(); + clear(self); + Arrays.unsafeSetLength(self._data, size); + } + + /** + * @dev Clear all data in the buffer without resetting memory, keeping the existing size. + */ + function clear(Bytes32CircularBuffer storage self) internal { + self._count = 0; + } + + /** + * @dev Push a new value to the buffer. If the buffer is already full, the new value replaces the oldest value in + * the buffer. + */ + function push(Bytes32CircularBuffer storage self, bytes32 value) internal { + uint256 index = self._count++; + uint256 modulus = self._data.length; + Arrays.unsafeAccess(self._data, index % modulus).value = value; + } + + /** + * @dev Number of values currently in the buffer. This value is 0 for an empty buffer, and cannot exceed the size of + * the buffer. + */ + function count(Bytes32CircularBuffer storage self) internal view returns (uint256) { + return Math.min(self._count, self._data.length); + } + + /** + * @dev Length of the buffer. This is the maximum number of elements kept in the buffer. + */ + function length(Bytes32CircularBuffer storage self) internal view returns (uint256) { + return self._data.length; + } + + /** + * @dev Getter for the i-th value in the buffer, from the end. + * + * Reverts with {Panic-ARRAY_OUT_OF_BOUNDS} if trying to access an element that was not pushed, or that was + * dropped to make room for newer elements. + */ + function last(Bytes32CircularBuffer storage self, uint256 i) internal view returns (bytes32) { + uint256 index = self._count; + uint256 modulus = self._data.length; + uint256 total = Math.min(index, modulus); // count(self) + if (i >= total) { + Panic.panic(Panic.ARRAY_OUT_OF_BOUNDS); + } + return Arrays.unsafeAccess(self._data, (index - i - 1) % modulus).value; + } + + /** + * @dev Check if a given value is in the buffer. + */ + function includes(Bytes32CircularBuffer storage self, bytes32 value) internal view returns (bool) { + uint256 index = self._count; + uint256 modulus = self._data.length; + uint256 total = Math.min(index, modulus); // count(self) + for (uint256 i = 0; i < total; ++i) { + if (Arrays.unsafeAccess(self._data, (index - i - 1) % modulus).value == value) { + return true; + } + } + return false; + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/utils/structs/DoubleEndedQueue.sol b/dependencies/@openzeppelin-contracts-5.4.0/utils/structs/DoubleEndedQueue.sol new file mode 100644 index 00000000..f243243b --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/utils/structs/DoubleEndedQueue.sol @@ -0,0 +1,156 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.1.0) (utils/structs/DoubleEndedQueue.sol) +pragma solidity ^0.8.20; + +import {Panic} from "../Panic.sol"; + +/** + * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of + * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and + * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that + * the existing queue contents are left in storage. + * + * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be + * used in storage, and not in memory. + * ```solidity + * DoubleEndedQueue.Bytes32Deque queue; + * ``` + */ +library DoubleEndedQueue { + /** + * @dev Indices are 128 bits so begin and end are packed in a single storage slot for efficient access. + * + * Struct members have an underscore prefix indicating that they are "private" and should not be read or written to + * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and + * lead to unexpected behavior. + * + * The first item is at data[begin] and the last item is at data[end - 1]. This range can wrap around. + */ + struct Bytes32Deque { + uint128 _begin; + uint128 _end; + mapping(uint128 index => bytes32) _data; + } + + /** + * @dev Inserts an item at the end of the queue. + * + * Reverts with {Panic-RESOURCE_ERROR} if the queue is full. + */ + function pushBack(Bytes32Deque storage deque, bytes32 value) internal { + unchecked { + uint128 backIndex = deque._end; + if (backIndex + 1 == deque._begin) Panic.panic(Panic.RESOURCE_ERROR); + deque._data[backIndex] = value; + deque._end = backIndex + 1; + } + } + + /** + * @dev Removes the item at the end of the queue and returns it. + * + * Reverts with {Panic-EMPTY_ARRAY_POP} if the queue is empty. + */ + function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) { + unchecked { + uint128 backIndex = deque._end; + if (backIndex == deque._begin) Panic.panic(Panic.EMPTY_ARRAY_POP); + --backIndex; + value = deque._data[backIndex]; + delete deque._data[backIndex]; + deque._end = backIndex; + } + } + + /** + * @dev Inserts an item at the beginning of the queue. + * + * Reverts with {Panic-RESOURCE_ERROR} if the queue is full. + */ + function pushFront(Bytes32Deque storage deque, bytes32 value) internal { + unchecked { + uint128 frontIndex = deque._begin - 1; + if (frontIndex == deque._end) Panic.panic(Panic.RESOURCE_ERROR); + deque._data[frontIndex] = value; + deque._begin = frontIndex; + } + } + + /** + * @dev Removes the item at the beginning of the queue and returns it. + * + * Reverts with {Panic-EMPTY_ARRAY_POP} if the queue is empty. + */ + function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) { + unchecked { + uint128 frontIndex = deque._begin; + if (frontIndex == deque._end) Panic.panic(Panic.EMPTY_ARRAY_POP); + value = deque._data[frontIndex]; + delete deque._data[frontIndex]; + deque._begin = frontIndex + 1; + } + } + + /** + * @dev Returns the item at the beginning of the queue. + * + * Reverts with {Panic-ARRAY_OUT_OF_BOUNDS} if the queue is empty. + */ + function front(Bytes32Deque storage deque) internal view returns (bytes32 value) { + if (empty(deque)) Panic.panic(Panic.ARRAY_OUT_OF_BOUNDS); + return deque._data[deque._begin]; + } + + /** + * @dev Returns the item at the end of the queue. + * + * Reverts with {Panic-ARRAY_OUT_OF_BOUNDS} if the queue is empty. + */ + function back(Bytes32Deque storage deque) internal view returns (bytes32 value) { + if (empty(deque)) Panic.panic(Panic.ARRAY_OUT_OF_BOUNDS); + unchecked { + return deque._data[deque._end - 1]; + } + } + + /** + * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at + * `length(deque) - 1`. + * + * Reverts with {Panic-ARRAY_OUT_OF_BOUNDS} if the index is out of bounds. + */ + function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) { + if (index >= length(deque)) Panic.panic(Panic.ARRAY_OUT_OF_BOUNDS); + // By construction, length is a uint128, so the check above ensures that index can be safely downcast to uint128 + unchecked { + return deque._data[deque._begin + uint128(index)]; + } + } + + /** + * @dev Resets the queue back to being empty. + * + * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses + * out on potential gas refunds. + */ + function clear(Bytes32Deque storage deque) internal { + deque._begin = 0; + deque._end = 0; + } + + /** + * @dev Returns the number of items in the queue. + */ + function length(Bytes32Deque storage deque) internal view returns (uint256) { + unchecked { + return uint256(deque._end - deque._begin); + } + } + + /** + * @dev Returns true if the queue is empty. + */ + function empty(Bytes32Deque storage deque) internal view returns (bool) { + return deque._end == deque._begin; + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/utils/structs/EnumerableMap.sol b/dependencies/@openzeppelin-contracts-5.4.0/utils/structs/EnumerableMap.sol new file mode 100644 index 00000000..68ce3223 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/utils/structs/EnumerableMap.sol @@ -0,0 +1,1319 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (utils/structs/EnumerableMap.sol) +// This file was procedurally generated from scripts/generate/templates/EnumerableMap.js. + +pragma solidity ^0.8.20; + +import {EnumerableSet} from "./EnumerableSet.sol"; + +/** + * @dev Library for managing an enumerable variant of Solidity's + * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`] + * type. + * + * Maps have the following properties: + * + * - 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 { + * // Add the library methods + * using EnumerableMap for EnumerableMap.UintToAddressMap; + * + * // Declare a set state variable + * EnumerableMap.UintToAddressMap private myMap; + * } + * ``` + * + * The following map types are supported: + * + * - `uint256 -> address` (`UintToAddressMap`) since v3.0.0 + * - `address -> uint256` (`AddressToUintMap`) since v4.6.0 + * - `bytes32 -> bytes32` (`Bytes32ToBytes32Map`) since v4.6.0 + * - `uint256 -> uint256` (`UintToUintMap`) since v4.7.0 + * - `bytes32 -> uint256` (`Bytes32ToUintMap`) since v4.7.0 + * - `uint256 -> bytes32` (`UintToBytes32Map`) since v5.1.0 + * - `address -> address` (`AddressToAddressMap`) since v5.1.0 + * - `address -> bytes32` (`AddressToBytes32Map`) since v5.1.0 + * - `bytes32 -> address` (`Bytes32ToAddressMap`) since v5.1.0 + * - `bytes -> bytes` (`BytesToBytesMap`) since v5.4.0 + * + * [WARNING] + * ==== + * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure + * unusable. + * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. + * + * In order to clean an EnumerableMap, you can either remove all elements one by one or create a fresh instance using an + * array of EnumerableMap. + * ==== + */ +library EnumerableMap { + using EnumerableSet for *; + + // To implement this library for multiple types with as little code repetition as possible, we write it in + // terms of a generic Map type with bytes32 keys and values. The Map implementation uses private functions, + // and user-facing implementations such as `UintToAddressMap` are just wrappers around the underlying Map. + // This means that we can only create new EnumerableMaps for types that fit in bytes32. + + /** + * @dev Query for a nonexistent map key. + */ + error EnumerableMapNonexistentKey(bytes32 key); + + struct Bytes32ToBytes32Map { + // Storage of keys + EnumerableSet.Bytes32Set _keys; + mapping(bytes32 key => bytes32) _values; + } + + /** + * @dev Adds a key-value pair to a map, or updates the value for an existing + * key. O(1). + * + * Returns true if the key was added to the map, that is if it was not + * already present. + */ + function set(Bytes32ToBytes32Map storage map, bytes32 key, bytes32 value) internal returns (bool) { + map._values[key] = value; + return map._keys.add(key); + } + + /** + * @dev Removes a key-value pair from a map. O(1). + * + * Returns true if the key was removed from the map, that is if it was present. + */ + function remove(Bytes32ToBytes32Map storage map, bytes32 key) internal returns (bool) { + delete map._values[key]; + 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). + */ + function contains(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bool) { + return map._keys.contains(key); + } + + /** + * @dev Returns the number of key-value pairs in the map. O(1). + */ + function length(Bytes32ToBytes32Map storage map) internal view returns (uint256) { + return map._keys.length(); + } + + /** + * @dev Returns the key-value pair stored at position `index` in the map. O(1). + * + * Note that there are no guarantees on the ordering of entries inside the + * array, and it may change when more entries are added or removed. + * + * Requirements: + * + * - `index` must be strictly less than {length}. + */ + function at(Bytes32ToBytes32Map storage map, uint256 index) internal view returns (bytes32 key, bytes32 value) { + bytes32 atKey = map._keys.at(index); + return (atKey, map._values[atKey]); + } + + /** + * @dev Tries to return the value associated with `key`. O(1). + * Does not revert if `key` is not in the map. + */ + function tryGet(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bool exists, bytes32 value) { + bytes32 val = map._values[key]; + if (val == bytes32(0)) { + return (contains(map, key), bytes32(0)); + } else { + return (true, val); + } + } + + /** + * @dev Returns the value associated with `key`. O(1). + * + * Requirements: + * + * - `key` must be in the map. + */ + function get(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bytes32) { + bytes32 value = map._values[key]; + if (value == 0 && !contains(map, key)) { + revert EnumerableMapNonexistentKey(key); + } + return value; + } + + /** + * @dev Returns an array containing all the keys + * + * 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 map grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function keys(Bytes32ToBytes32Map storage map) internal view returns (bytes32[] memory) { + return map._keys.values(); + } + + /** + * @dev Returns an array containing a slice of the keys + * + * 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 map grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function keys( + Bytes32ToBytes32Map storage map, + uint256 start, + uint256 end + ) internal view returns (bytes32[] memory) { + return map._keys.values(start, end); + } + + // UintToUintMap + + struct UintToUintMap { + Bytes32ToBytes32Map _inner; + } + + /** + * @dev Adds a key-value pair to a map, or updates the value for an existing + * key. O(1). + * + * Returns true if the key was added to the map, that is if it was not + * already present. + */ + function set(UintToUintMap storage map, uint256 key, uint256 value) internal returns (bool) { + return set(map._inner, bytes32(key), bytes32(value)); + } + + /** + * @dev Removes a value from a map. O(1). + * + * Returns true if the key was removed from the map, that is if it was present. + */ + function remove(UintToUintMap storage map, uint256 key) internal returns (bool) { + return remove(map._inner, bytes32(key)); + } + + /** + * @dev Removes all the entries from a map. O(n). + * + * WARNING: This function has an unbounded cost that scales with map size. Developers should keep in mind that + * 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(UintToUintMap storage map) internal { + clear(map._inner); + } + + /** + * @dev Returns true if the key is in the map. O(1). + */ + function contains(UintToUintMap storage map, uint256 key) internal view returns (bool) { + return contains(map._inner, bytes32(key)); + } + + /** + * @dev Returns the number of elements in the map. O(1). + */ + function length(UintToUintMap storage map) internal view returns (uint256) { + return length(map._inner); + } + + /** + * @dev Returns the element stored at position `index` in the map. 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(UintToUintMap storage map, uint256 index) internal view returns (uint256 key, uint256 value) { + (bytes32 atKey, bytes32 val) = at(map._inner, index); + return (uint256(atKey), uint256(val)); + } + + /** + * @dev Tries to return the value associated with `key`. O(1). + * Does not revert if `key` is not in the map. + */ + function tryGet(UintToUintMap storage map, uint256 key) internal view returns (bool exists, uint256 value) { + (bool success, bytes32 val) = tryGet(map._inner, bytes32(key)); + return (success, uint256(val)); + } + + /** + * @dev Returns the value associated with `key`. O(1). + * + * Requirements: + * + * - `key` must be in the map. + */ + function get(UintToUintMap storage map, uint256 key) internal view returns (uint256) { + return uint256(get(map._inner, bytes32(key))); + } + + /** + * @dev Returns an array containing all the keys + * + * 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 map grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function keys(UintToUintMap storage map) internal view returns (uint256[] memory) { + bytes32[] memory store = keys(map._inner); + uint256[] memory result; + + assembly ("memory-safe") { + result := store + } + + return result; + } + + /** + * @dev Returns an array containing a slice of the keys + * + * 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 map grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function keys(UintToUintMap storage map, uint256 start, uint256 end) internal view returns (uint256[] memory) { + bytes32[] memory store = keys(map._inner, start, end); + uint256[] memory result; + + assembly ("memory-safe") { + result := store + } + + return result; + } + + // UintToAddressMap + + struct UintToAddressMap { + Bytes32ToBytes32Map _inner; + } + + /** + * @dev Adds a key-value pair to a map, or updates the value for an existing + * key. O(1). + * + * Returns true if the key was added to the map, that is if it was not + * already present. + */ + function set(UintToAddressMap storage map, uint256 key, address value) internal returns (bool) { + return set(map._inner, bytes32(key), bytes32(uint256(uint160(value)))); + } + + /** + * @dev Removes a value from a map. O(1). + * + * Returns true if the key was removed from the map, that is if it was present. + */ + function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) { + return remove(map._inner, bytes32(key)); + } + + /** + * @dev Removes all the entries from a map. O(n). + * + * WARNING: This function has an unbounded cost that scales with map size. Developers should keep in mind that + * 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(UintToAddressMap storage map) internal { + clear(map._inner); + } + + /** + * @dev Returns true if the key is in the map. O(1). + */ + function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) { + return contains(map._inner, bytes32(key)); + } + + /** + * @dev Returns the number of elements in the map. O(1). + */ + function length(UintToAddressMap storage map) internal view returns (uint256) { + return length(map._inner); + } + + /** + * @dev Returns the element stored at position `index` in the map. 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(UintToAddressMap storage map, uint256 index) internal view returns (uint256 key, address value) { + (bytes32 atKey, bytes32 val) = at(map._inner, index); + return (uint256(atKey), address(uint160(uint256(val)))); + } + + /** + * @dev Tries to return the value associated with `key`. O(1). + * Does not revert if `key` is not in the map. + */ + function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool exists, address value) { + (bool success, bytes32 val) = tryGet(map._inner, bytes32(key)); + return (success, address(uint160(uint256(val)))); + } + + /** + * @dev Returns the value associated with `key`. O(1). + * + * Requirements: + * + * - `key` must be in the map. + */ + function get(UintToAddressMap storage map, uint256 key) internal view returns (address) { + return address(uint160(uint256(get(map._inner, bytes32(key))))); + } + + /** + * @dev Returns an array containing all the keys + * + * 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 map grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function keys(UintToAddressMap storage map) internal view returns (uint256[] memory) { + bytes32[] memory store = keys(map._inner); + uint256[] memory result; + + assembly ("memory-safe") { + result := store + } + + return result; + } + + /** + * @dev Returns an array containing a slice of the keys + * + * 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 map grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function keys(UintToAddressMap storage map, uint256 start, uint256 end) internal view returns (uint256[] memory) { + bytes32[] memory store = keys(map._inner, start, end); + uint256[] memory result; + + assembly ("memory-safe") { + result := store + } + + return result; + } + + // UintToBytes32Map + + struct UintToBytes32Map { + Bytes32ToBytes32Map _inner; + } + + /** + * @dev Adds a key-value pair to a map, or updates the value for an existing + * key. O(1). + * + * Returns true if the key was added to the map, that is if it was not + * already present. + */ + function set(UintToBytes32Map storage map, uint256 key, bytes32 value) internal returns (bool) { + return set(map._inner, bytes32(key), value); + } + + /** + * @dev Removes a value from a map. O(1). + * + * Returns true if the key was removed from the map, that is if it was present. + */ + function remove(UintToBytes32Map storage map, uint256 key) internal returns (bool) { + return remove(map._inner, bytes32(key)); + } + + /** + * @dev Removes all the entries from a map. O(n). + * + * WARNING: This function has an unbounded cost that scales with map size. Developers should keep in mind that + * 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(UintToBytes32Map storage map) internal { + clear(map._inner); + } + + /** + * @dev Returns true if the key is in the map. O(1). + */ + function contains(UintToBytes32Map storage map, uint256 key) internal view returns (bool) { + return contains(map._inner, bytes32(key)); + } + + /** + * @dev Returns the number of elements in the map. O(1). + */ + function length(UintToBytes32Map storage map) internal view returns (uint256) { + return length(map._inner); + } + + /** + * @dev Returns the element stored at position `index` in the map. 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(UintToBytes32Map storage map, uint256 index) internal view returns (uint256 key, bytes32 value) { + (bytes32 atKey, bytes32 val) = at(map._inner, index); + return (uint256(atKey), val); + } + + /** + * @dev Tries to return the value associated with `key`. O(1). + * Does not revert if `key` is not in the map. + */ + function tryGet(UintToBytes32Map storage map, uint256 key) internal view returns (bool exists, bytes32 value) { + (bool success, bytes32 val) = tryGet(map._inner, bytes32(key)); + return (success, val); + } + + /** + * @dev Returns the value associated with `key`. O(1). + * + * Requirements: + * + * - `key` must be in the map. + */ + function get(UintToBytes32Map storage map, uint256 key) internal view returns (bytes32) { + return get(map._inner, bytes32(key)); + } + + /** + * @dev Returns an array containing all the keys + * + * 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 map grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function keys(UintToBytes32Map storage map) internal view returns (uint256[] memory) { + bytes32[] memory store = keys(map._inner); + uint256[] memory result; + + assembly ("memory-safe") { + result := store + } + + return result; + } + + /** + * @dev Returns an array containing a slice of the keys + * + * 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 map grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function keys(UintToBytes32Map storage map, uint256 start, uint256 end) internal view returns (uint256[] memory) { + bytes32[] memory store = keys(map._inner, start, end); + uint256[] memory result; + + assembly ("memory-safe") { + result := store + } + + return result; + } + + // AddressToUintMap + + struct AddressToUintMap { + Bytes32ToBytes32Map _inner; + } + + /** + * @dev Adds a key-value pair to a map, or updates the value for an existing + * key. O(1). + * + * Returns true if the key was added to the map, that is if it was not + * already present. + */ + function set(AddressToUintMap storage map, address key, uint256 value) internal returns (bool) { + return set(map._inner, bytes32(uint256(uint160(key))), bytes32(value)); + } + + /** + * @dev Removes a value from a map. O(1). + * + * Returns true if the key was removed from the map, that is if it was present. + */ + function remove(AddressToUintMap storage map, address key) internal returns (bool) { + return remove(map._inner, bytes32(uint256(uint160(key)))); + } + + /** + * @dev Removes all the entries from a map. O(n). + * + * WARNING: This function has an unbounded cost that scales with map size. Developers should keep in mind that + * 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(AddressToUintMap storage map) internal { + clear(map._inner); + } + + /** + * @dev Returns true if the key is in the map. O(1). + */ + function contains(AddressToUintMap storage map, address key) internal view returns (bool) { + return contains(map._inner, bytes32(uint256(uint160(key)))); + } + + /** + * @dev Returns the number of elements in the map. O(1). + */ + function length(AddressToUintMap storage map) internal view returns (uint256) { + return length(map._inner); + } + + /** + * @dev Returns the element stored at position `index` in the map. 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(AddressToUintMap storage map, uint256 index) internal view returns (address key, uint256 value) { + (bytes32 atKey, bytes32 val) = at(map._inner, index); + return (address(uint160(uint256(atKey))), uint256(val)); + } + + /** + * @dev Tries to return the value associated with `key`. O(1). + * Does not revert if `key` is not in the map. + */ + function tryGet(AddressToUintMap storage map, address key) internal view returns (bool exists, uint256 value) { + (bool success, bytes32 val) = tryGet(map._inner, bytes32(uint256(uint160(key)))); + return (success, uint256(val)); + } + + /** + * @dev Returns the value associated with `key`. O(1). + * + * Requirements: + * + * - `key` must be in the map. + */ + function get(AddressToUintMap storage map, address key) internal view returns (uint256) { + return uint256(get(map._inner, bytes32(uint256(uint160(key))))); + } + + /** + * @dev Returns an array containing all the keys + * + * 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 map grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function keys(AddressToUintMap storage map) internal view returns (address[] memory) { + bytes32[] memory store = keys(map._inner); + address[] memory result; + + assembly ("memory-safe") { + result := store + } + + return result; + } + + /** + * @dev Returns an array containing a slice of the keys + * + * 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 map grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function keys(AddressToUintMap storage map, uint256 start, uint256 end) internal view returns (address[] memory) { + bytes32[] memory store = keys(map._inner, start, end); + address[] memory result; + + assembly ("memory-safe") { + result := store + } + + return result; + } + + // AddressToAddressMap + + struct AddressToAddressMap { + Bytes32ToBytes32Map _inner; + } + + /** + * @dev Adds a key-value pair to a map, or updates the value for an existing + * key. O(1). + * + * Returns true if the key was added to the map, that is if it was not + * already present. + */ + function set(AddressToAddressMap storage map, address key, address value) internal returns (bool) { + return set(map._inner, bytes32(uint256(uint160(key))), bytes32(uint256(uint160(value)))); + } + + /** + * @dev Removes a value from a map. O(1). + * + * Returns true if the key was removed from the map, that is if it was present. + */ + function remove(AddressToAddressMap storage map, address key) internal returns (bool) { + return remove(map._inner, bytes32(uint256(uint160(key)))); + } + + /** + * @dev Removes all the entries from a map. O(n). + * + * WARNING: This function has an unbounded cost that scales with map size. Developers should keep in mind that + * 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(AddressToAddressMap storage map) internal { + clear(map._inner); + } + + /** + * @dev Returns true if the key is in the map. O(1). + */ + function contains(AddressToAddressMap storage map, address key) internal view returns (bool) { + return contains(map._inner, bytes32(uint256(uint160(key)))); + } + + /** + * @dev Returns the number of elements in the map. O(1). + */ + function length(AddressToAddressMap storage map) internal view returns (uint256) { + return length(map._inner); + } + + /** + * @dev Returns the element stored at position `index` in the map. 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(AddressToAddressMap storage map, uint256 index) internal view returns (address key, address value) { + (bytes32 atKey, bytes32 val) = at(map._inner, index); + return (address(uint160(uint256(atKey))), address(uint160(uint256(val)))); + } + + /** + * @dev Tries to return the value associated with `key`. O(1). + * Does not revert if `key` is not in the map. + */ + function tryGet(AddressToAddressMap storage map, address key) internal view returns (bool exists, address value) { + (bool success, bytes32 val) = tryGet(map._inner, bytes32(uint256(uint160(key)))); + return (success, address(uint160(uint256(val)))); + } + + /** + * @dev Returns the value associated with `key`. O(1). + * + * Requirements: + * + * - `key` must be in the map. + */ + function get(AddressToAddressMap storage map, address key) internal view returns (address) { + return address(uint160(uint256(get(map._inner, bytes32(uint256(uint160(key))))))); + } + + /** + * @dev Returns an array containing all the keys + * + * 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 map grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function keys(AddressToAddressMap storage map) internal view returns (address[] memory) { + bytes32[] memory store = keys(map._inner); + address[] memory result; + + assembly ("memory-safe") { + result := store + } + + return result; + } + + /** + * @dev Returns an array containing a slice of the keys + * + * 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 map grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function keys( + AddressToAddressMap storage map, + uint256 start, + uint256 end + ) internal view returns (address[] memory) { + bytes32[] memory store = keys(map._inner, start, end); + address[] memory result; + + assembly ("memory-safe") { + result := store + } + + return result; + } + + // AddressToBytes32Map + + struct AddressToBytes32Map { + Bytes32ToBytes32Map _inner; + } + + /** + * @dev Adds a key-value pair to a map, or updates the value for an existing + * key. O(1). + * + * Returns true if the key was added to the map, that is if it was not + * already present. + */ + function set(AddressToBytes32Map storage map, address key, bytes32 value) internal returns (bool) { + return set(map._inner, bytes32(uint256(uint160(key))), value); + } + + /** + * @dev Removes a value from a map. O(1). + * + * Returns true if the key was removed from the map, that is if it was present. + */ + function remove(AddressToBytes32Map storage map, address key) internal returns (bool) { + return remove(map._inner, bytes32(uint256(uint160(key)))); + } + + /** + * @dev Removes all the entries from a map. O(n). + * + * WARNING: This function has an unbounded cost that scales with map size. Developers should keep in mind that + * 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(AddressToBytes32Map storage map) internal { + clear(map._inner); + } + + /** + * @dev Returns true if the key is in the map. O(1). + */ + function contains(AddressToBytes32Map storage map, address key) internal view returns (bool) { + return contains(map._inner, bytes32(uint256(uint160(key)))); + } + + /** + * @dev Returns the number of elements in the map. O(1). + */ + function length(AddressToBytes32Map storage map) internal view returns (uint256) { + return length(map._inner); + } + + /** + * @dev Returns the element stored at position `index` in the map. 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(AddressToBytes32Map storage map, uint256 index) internal view returns (address key, bytes32 value) { + (bytes32 atKey, bytes32 val) = at(map._inner, index); + return (address(uint160(uint256(atKey))), val); + } + + /** + * @dev Tries to return the value associated with `key`. O(1). + * Does not revert if `key` is not in the map. + */ + function tryGet(AddressToBytes32Map storage map, address key) internal view returns (bool exists, bytes32 value) { + (bool success, bytes32 val) = tryGet(map._inner, bytes32(uint256(uint160(key)))); + return (success, val); + } + + /** + * @dev Returns the value associated with `key`. O(1). + * + * Requirements: + * + * - `key` must be in the map. + */ + function get(AddressToBytes32Map storage map, address key) internal view returns (bytes32) { + return get(map._inner, bytes32(uint256(uint160(key)))); + } + + /** + * @dev Returns an array containing all the keys + * + * 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 map grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function keys(AddressToBytes32Map storage map) internal view returns (address[] memory) { + bytes32[] memory store = keys(map._inner); + address[] memory result; + + assembly ("memory-safe") { + result := store + } + + return result; + } + + /** + * @dev Returns an array containing a slice of the keys + * + * 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 map grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function keys( + AddressToBytes32Map storage map, + uint256 start, + uint256 end + ) internal view returns (address[] memory) { + bytes32[] memory store = keys(map._inner, start, end); + address[] memory result; + + assembly ("memory-safe") { + result := store + } + + return result; + } + + // Bytes32ToUintMap + + struct Bytes32ToUintMap { + Bytes32ToBytes32Map _inner; + } + + /** + * @dev Adds a key-value pair to a map, or updates the value for an existing + * key. O(1). + * + * Returns true if the key was added to the map, that is if it was not + * already present. + */ + function set(Bytes32ToUintMap storage map, bytes32 key, uint256 value) internal returns (bool) { + return set(map._inner, key, bytes32(value)); + } + + /** + * @dev Removes a value from a map. O(1). + * + * Returns true if the key was removed from the map, that is if it was present. + */ + function remove(Bytes32ToUintMap storage map, bytes32 key) internal returns (bool) { + return remove(map._inner, key); + } + + /** + * @dev Removes all the entries from a map. O(n). + * + * WARNING: This function has an unbounded cost that scales with map size. Developers should keep in mind that + * 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(Bytes32ToUintMap storage map) internal { + clear(map._inner); + } + + /** + * @dev Returns true if the key is in the map. O(1). + */ + function contains(Bytes32ToUintMap storage map, bytes32 key) internal view returns (bool) { + return contains(map._inner, key); + } + + /** + * @dev Returns the number of elements in the map. O(1). + */ + function length(Bytes32ToUintMap storage map) internal view returns (uint256) { + return length(map._inner); + } + + /** + * @dev Returns the element stored at position `index` in the map. 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(Bytes32ToUintMap storage map, uint256 index) internal view returns (bytes32 key, uint256 value) { + (bytes32 atKey, bytes32 val) = at(map._inner, index); + return (atKey, uint256(val)); + } + + /** + * @dev Tries to return the value associated with `key`. O(1). + * Does not revert if `key` is not in the map. + */ + function tryGet(Bytes32ToUintMap storage map, bytes32 key) internal view returns (bool exists, uint256 value) { + (bool success, bytes32 val) = tryGet(map._inner, key); + return (success, uint256(val)); + } + + /** + * @dev Returns the value associated with `key`. O(1). + * + * Requirements: + * + * - `key` must be in the map. + */ + function get(Bytes32ToUintMap storage map, bytes32 key) internal view returns (uint256) { + return uint256(get(map._inner, key)); + } + + /** + * @dev Returns an array containing all the keys + * + * 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 map grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function keys(Bytes32ToUintMap storage map) internal view returns (bytes32[] memory) { + bytes32[] memory store = keys(map._inner); + bytes32[] memory result; + + assembly ("memory-safe") { + result := store + } + + return result; + } + + /** + * @dev Returns an array containing a slice of the keys + * + * 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 map grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function keys(Bytes32ToUintMap storage map, uint256 start, uint256 end) internal view returns (bytes32[] memory) { + bytes32[] memory store = keys(map._inner, start, end); + bytes32[] memory result; + + assembly ("memory-safe") { + result := store + } + + return result; + } + + // Bytes32ToAddressMap + + struct Bytes32ToAddressMap { + Bytes32ToBytes32Map _inner; + } + + /** + * @dev Adds a key-value pair to a map, or updates the value for an existing + * key. O(1). + * + * Returns true if the key was added to the map, that is if it was not + * already present. + */ + function set(Bytes32ToAddressMap storage map, bytes32 key, address value) internal returns (bool) { + return set(map._inner, key, bytes32(uint256(uint160(value)))); + } + + /** + * @dev Removes a value from a map. O(1). + * + * Returns true if the key was removed from the map, that is if it was present. + */ + function remove(Bytes32ToAddressMap storage map, bytes32 key) internal returns (bool) { + return remove(map._inner, key); + } + + /** + * @dev Removes all the entries from a map. O(n). + * + * WARNING: This function has an unbounded cost that scales with map size. Developers should keep in mind that + * 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(Bytes32ToAddressMap storage map) internal { + clear(map._inner); + } + + /** + * @dev Returns true if the key is in the map. O(1). + */ + function contains(Bytes32ToAddressMap storage map, bytes32 key) internal view returns (bool) { + return contains(map._inner, key); + } + + /** + * @dev Returns the number of elements in the map. O(1). + */ + function length(Bytes32ToAddressMap storage map) internal view returns (uint256) { + return length(map._inner); + } + + /** + * @dev Returns the element stored at position `index` in the map. 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(Bytes32ToAddressMap storage map, uint256 index) internal view returns (bytes32 key, address value) { + (bytes32 atKey, bytes32 val) = at(map._inner, index); + return (atKey, address(uint160(uint256(val)))); + } + + /** + * @dev Tries to return the value associated with `key`. O(1). + * Does not revert if `key` is not in the map. + */ + function tryGet(Bytes32ToAddressMap storage map, bytes32 key) internal view returns (bool exists, address value) { + (bool success, bytes32 val) = tryGet(map._inner, key); + return (success, address(uint160(uint256(val)))); + } + + /** + * @dev Returns the value associated with `key`. O(1). + * + * Requirements: + * + * - `key` must be in the map. + */ + function get(Bytes32ToAddressMap storage map, bytes32 key) internal view returns (address) { + return address(uint160(uint256(get(map._inner, key)))); + } + + /** + * @dev Returns an array containing all the keys + * + * 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 map grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function keys(Bytes32ToAddressMap storage map) internal view returns (bytes32[] memory) { + bytes32[] memory store = keys(map._inner); + bytes32[] memory result; + + assembly ("memory-safe") { + result := store + } + + return result; + } + + /** + * @dev Returns an array containing a slice of the keys + * + * 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 map grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function keys( + Bytes32ToAddressMap storage map, + uint256 start, + uint256 end + ) internal view returns (bytes32[] memory) { + bytes32[] memory store = keys(map._inner, start, end); + bytes32[] memory result; + + assembly ("memory-safe") { + result := store + } + + return result; + } + + /** + * @dev Query for a nonexistent map key. + */ + error EnumerableMapNonexistentBytesKey(bytes key); + + struct BytesToBytesMap { + // Storage of keys + EnumerableSet.BytesSet _keys; + mapping(bytes key => bytes) _values; + } + + /** + * @dev Adds a key-value pair to a map, or updates the value for an existing + * key. O(1). + * + * Returns true if the key was added to the map, that is if it was not + * already present. + */ + function set(BytesToBytesMap storage map, bytes memory key, bytes memory value) internal returns (bool) { + map._values[key] = value; + return map._keys.add(key); + } + + /** + * @dev Removes a key-value pair from a map. O(1). + * + * Returns true if the key was removed from the map, that is if it was present. + */ + function remove(BytesToBytesMap storage map, bytes memory key) internal returns (bool) { + delete map._values[key]; + 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(BytesToBytesMap 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). + */ + function contains(BytesToBytesMap storage map, bytes memory key) internal view returns (bool) { + return map._keys.contains(key); + } + + /** + * @dev Returns the number of key-value pairs in the map. O(1). + */ + function length(BytesToBytesMap storage map) internal view returns (uint256) { + return map._keys.length(); + } + + /** + * @dev Returns the key-value pair stored at position `index` in the map. O(1). + * + * Note that there are no guarantees on the ordering of entries inside the + * array, and it may change when more entries are added or removed. + * + * Requirements: + * + * - `index` must be strictly less than {length}. + */ + function at( + BytesToBytesMap storage map, + uint256 index + ) internal view returns (bytes memory key, bytes memory value) { + key = map._keys.at(index); + value = map._values[key]; + } + + /** + * @dev Tries to return the value associated with `key`. O(1). + * Does not revert if `key` is not in the map. + */ + function tryGet( + BytesToBytesMap storage map, + bytes memory key + ) internal view returns (bool exists, bytes memory value) { + value = map._values[key]; + exists = bytes(value).length != 0 || contains(map, key); + } + + /** + * @dev Returns the value associated with `key`. O(1). + * + * Requirements: + * + * - `key` must be in the map. + */ + function get(BytesToBytesMap storage map, bytes memory key) internal view returns (bytes memory value) { + bool exists; + (exists, value) = tryGet(map, key); + if (!exists) { + revert EnumerableMapNonexistentBytesKey(key); + } + } + + /** + * @dev Returns an array containing all the keys + * + * 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 map grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function keys(BytesToBytesMap storage map) internal view returns (bytes[] memory) { + return map._keys.values(); + } + + /** + * @dev Returns an array containing a slice of the keys + * + * 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 map grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function keys(BytesToBytesMap storage map, uint256 start, uint256 end) internal view returns (bytes[] memory) { + return map._keys.values(start, end); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/utils/structs/EnumerableSet.sol b/dependencies/@openzeppelin-contracts-5.4.0/utils/structs/EnumerableSet.sol new file mode 100644 index 00000000..fbf742a6 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/utils/structs/EnumerableSet.sol @@ -0,0 +1,792 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (utils/structs/EnumerableSet.sol) +// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js. + +pragma solidity ^0.8.20; + +import {Arrays} from "../Arrays.sol"; +import {Math} from "../math/Math.sol"; + +/** + * @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. + * - Set can be cleared (all elements removed) in O(n). + * + * ```solidity + * contract Example { + * // Add the library methods + * using EnumerableSet for EnumerableSet.AddressSet; + * + * // Declare a set state variable + * EnumerableSet.AddressSet private mySet; + * } + * ``` + * + * The following types are supported: + * + * - `bytes32` (`Bytes32Set`) since v3.3.0 + * - `address` (`AddressSet`) since v3.3.0 + * - `uint256` (`UintSet`) since v3.3.0 + * - `string` (`StringSet`) since v5.4.0 + * - `bytes` (`BytesSet`) since v5.4.0 + * + * [WARNING] + * ==== + * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure + * unusable. + * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. + * + * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an + * array of EnumerableSet. + * ==== + */ +library EnumerableSet { + // To implement this library for multiple types with as little code + // repetition as possible, we write it in terms of a generic Set type with + // bytes32 values. + // The Set implementation uses private functions, and user-facing + // implementations (such as AddressSet) are just wrappers around the + // underlying Set. + // This means that we can only create new EnumerableSets for types that fit + // in bytes32. + + struct Set { + // Storage of set values + bytes32[] _values; + // Position is the index of the value in the `values` array plus 1. + // Position 0 is used to mean a value is not in the set. + mapping(bytes32 value => uint256) _positions; + } + + /** + * @dev Add a value to a set. O(1). + * + * Returns true if the value was added to the set, that is if it was not + * already present. + */ + function _add(Set storage set, bytes32 value) private returns (bool) { + if (!_contains(set, value)) { + set._values.push(value); + // The value is stored at length-1, but we add 1 to all indexes + // and use 0 as a sentinel value + set._positions[value] = set._values.length; + return true; + } else { + return false; + } + } + + /** + * @dev Removes a value from a set. O(1). + * + * Returns true if the value was removed from the set, that is if it was + * present. + */ + function _remove(Set storage set, bytes32 value) private returns (bool) { + // We cache the value's position to prevent multiple reads from the same storage slot + uint256 position = set._positions[value]; + + if (position != 0) { + // Equivalent to contains(set, value) + // To delete an element from the _values array in O(1), we swap the element to delete with the last one in + // the array, and then remove the last element (sometimes called as 'swap and pop'). + // This modifies the order of the array, as noted in {at}. + + uint256 valueIndex = position - 1; + uint256 lastIndex = set._values.length - 1; + + if (valueIndex != lastIndex) { + bytes32 lastValue = set._values[lastIndex]; + + // Move the lastValue to the index where the value to delete is + set._values[valueIndex] = lastValue; + // Update the tracked position of the lastValue (that was just moved) + set._positions[lastValue] = position; + } + + // Delete the slot where the moved value was stored + set._values.pop(); + + // Delete the tracked position for the deleted slot + delete set._positions[value]; + + return true; + } else { + return false; + } + } + + /** + * @dev Removes all the values from a set. O(n). + * + * WARNING: This function has an unbounded cost that scales with set size. Developers should keep in mind that + * 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). + */ + function _contains(Set storage set, bytes32 value) private view returns (bool) { + return set._positions[value] != 0; + } + + /** + * @dev Returns the number of values on the set. O(1). + */ + function _length(Set storage set) private view returns (uint256) { + return set._values.length; + } + + /** + * @dev Returns the value stored at position `index` in the set. O(1). + * + * Note that there are no guarantees on the ordering of values inside the + * array, and it may change when more values are added or removed. + * + * Requirements: + * + * - `index` must be strictly less than {length}. + */ + function _at(Set storage set, uint256 index) private view returns (bytes32) { + return set._values[index]; + } + + /** + * @dev Return the entire set in an array + * + * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed + * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that + * this function has an unbounded cost, and using it as part of a state-changing function may render the function + * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function _values(Set storage set) private view returns (bytes32[] memory) { + return set._values; + } + + /** + * @dev Return a slice of the 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, uint256 start, uint256 end) private view returns (bytes32[] memory) { + unchecked { + end = Math.min(end, _length(set)); + start = Math.min(start, end); + + uint256 len = end - start; + bytes32[] memory result = new bytes32[](len); + for (uint256 i = 0; i < len; ++i) { + result[i] = Arrays.unsafeAccess(set._values, start + i).value; + } + return result; + } + } + + // 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 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(Bytes32Set storage set) internal { + _clear(set._inner); + } + + /** + * @dev Returns true if the value is in the set. O(1). + */ + function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { + return _contains(set._inner, value); + } + + /** + * @dev Returns the number of values in the set. O(1). + */ + function length(Bytes32Set storage set) internal view returns (uint256) { + return _length(set._inner); + } + + /** + * @dev Returns the value stored at position `index` in the set. O(1). + * + * Note that there are no guarantees on the ordering of values inside the + * array, and it may change when more values are added or removed. + * + * Requirements: + * + * - `index` must be strictly less than {length}. + */ + function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { + return _at(set._inner, index); + } + + /** + * @dev Return the entire set in an array + * + * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed + * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that + * this function has an unbounded cost, and using it as part of a state-changing function may render the function + * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { + bytes32[] memory store = _values(set._inner); + bytes32[] memory result; + + assembly ("memory-safe") { + result := store + } + + return result; + } + + /** + * @dev Return a slice of the 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, uint256 start, uint256 end) internal view returns (bytes32[] memory) { + bytes32[] memory store = _values(set._inner, start, end); + bytes32[] memory result; + + assembly ("memory-safe") { + result := store + } + + return result; + } + + // AddressSet + + struct AddressSet { + Set _inner; + } + + /** + * @dev Add a value to a set. O(1). + * + * Returns true if the value was added to the set, that is if it was not + * already present. + */ + function add(AddressSet storage set, address value) internal returns (bool) { + return _add(set._inner, bytes32(uint256(uint160(value)))); + } + + /** + * @dev Removes a value from a set. O(1). + * + * Returns true if the value was removed from the set, that is if it was + * present. + */ + function remove(AddressSet storage set, address value) internal returns (bool) { + return _remove(set._inner, bytes32(uint256(uint160(value)))); + } + + /** + * @dev 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(AddressSet storage set) internal { + _clear(set._inner); + } + + /** + * @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 ("memory-safe") { + result := store + } + + return result; + } + + /** + * @dev Return a slice of the 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, uint256 start, uint256 end) internal view returns (address[] memory) { + bytes32[] memory store = _values(set._inner, start, end); + address[] memory result; + + assembly ("memory-safe") { + 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 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(UintSet storage set) internal { + _clear(set._inner); + } + + /** + * @dev Returns true if the value is in the set. O(1). + */ + function contains(UintSet storage set, uint256 value) internal view returns (bool) { + return _contains(set._inner, bytes32(value)); + } + + /** + * @dev Returns the number of values in the set. O(1). + */ + function length(UintSet storage set) internal view returns (uint256) { + return _length(set._inner); + } + + /** + * @dev Returns the value stored at position `index` in the set. O(1). + * + * Note that there are no guarantees on the ordering of values inside the + * array, and it may change when more values are added or removed. + * + * Requirements: + * + * - `index` must be strictly less than {length}. + */ + function at(UintSet storage set, uint256 index) internal view returns (uint256) { + return uint256(_at(set._inner, index)); + } + + /** + * @dev Return the entire set in an array + * + * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed + * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that + * this function has an unbounded cost, and using it as part of a state-changing function may render the function + * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function values(UintSet storage set) internal view returns (uint256[] memory) { + bytes32[] memory store = _values(set._inner); + uint256[] memory result; + + assembly ("memory-safe") { + result := store + } + + return result; + } + + /** + * @dev Return a slice of the 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, uint256 start, uint256 end) internal view returns (uint256[] memory) { + bytes32[] memory store = _values(set._inner, start, end); + uint256[] memory result; + + assembly ("memory-safe") { + result := store + } + + return result; + } + + struct StringSet { + // Storage of set values + string[] _values; + // Position is the index of the value in the `values` array plus 1. + // Position 0 is used to mean a value is not in the set. + mapping(string value => uint256) _positions; + } + + /** + * @dev Add a value to a set. O(1). + * + * Returns true if the value was added to the set, that is if it was not + * already present. + */ + function add(StringSet storage set, string memory value) internal returns (bool) { + if (!contains(set, value)) { + set._values.push(value); + // The value is stored at length-1, but we add 1 to all indexes + // and use 0 as a sentinel value + set._positions[value] = set._values.length; + return true; + } else { + return false; + } + } + + /** + * @dev Removes a value from a set. O(1). + * + * Returns true if the value was removed from the set, that is if it was + * present. + */ + function remove(StringSet storage set, string memory value) internal returns (bool) { + // We cache the value's position to prevent multiple reads from the same storage slot + uint256 position = set._positions[value]; + + if (position != 0) { + // Equivalent to contains(set, value) + // To delete an element from the _values array in O(1), we swap the element to delete with the last one in + // the array, and then remove the last element (sometimes called as 'swap and pop'). + // This modifies the order of the array, as noted in {at}. + + uint256 valueIndex = position - 1; + uint256 lastIndex = set._values.length - 1; + + if (valueIndex != lastIndex) { + string memory lastValue = set._values[lastIndex]; + + // Move the lastValue to the index where the value to delete is + set._values[valueIndex] = lastValue; + // Update the tracked position of the lastValue (that was just moved) + set._positions[lastValue] = position; + } + + // Delete the slot where the moved value was stored + set._values.pop(); + + // Delete the tracked position for the deleted slot + delete set._positions[value]; + + return true; + } else { + return false; + } + } + + /** + * @dev 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(StringSet storage set) internal { + 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). + */ + function contains(StringSet storage set, string memory value) internal view returns (bool) { + return set._positions[value] != 0; + } + + /** + * @dev Returns the number of values on the set. O(1). + */ + function length(StringSet storage set) internal 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(StringSet storage set, uint256 index) internal view returns (string memory) { + 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(StringSet storage set) internal view returns (string[] memory) { + return set._values; + } + + /** + * @dev Return a slice of the 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(StringSet storage set, uint256 start, uint256 end) internal view returns (string[] memory) { + unchecked { + end = Math.min(end, length(set)); + start = Math.min(start, end); + + uint256 len = end - start; + string[] memory result = new string[](len); + for (uint256 i = 0; i < len; ++i) { + result[i] = Arrays.unsafeAccess(set._values, start + i).value; + } + return result; + } + } + + struct BytesSet { + // Storage of set values + bytes[] _values; + // Position is the index of the value in the `values` array plus 1. + // Position 0 is used to mean a value is not in the set. + mapping(bytes value => uint256) _positions; + } + + /** + * @dev Add a value to a set. O(1). + * + * Returns true if the value was added to the set, that is if it was not + * already present. + */ + function add(BytesSet storage set, bytes memory value) internal returns (bool) { + if (!contains(set, value)) { + set._values.push(value); + // The value is stored at length-1, but we add 1 to all indexes + // and use 0 as a sentinel value + set._positions[value] = set._values.length; + return true; + } else { + return false; + } + } + + /** + * @dev Removes a value from a set. O(1). + * + * Returns true if the value was removed from the set, that is if it was + * present. + */ + function remove(BytesSet storage set, bytes memory value) internal returns (bool) { + // We cache the value's position to prevent multiple reads from the same storage slot + uint256 position = set._positions[value]; + + if (position != 0) { + // Equivalent to contains(set, value) + // To delete an element from the _values array in O(1), we swap the element to delete with the last one in + // the array, and then remove the last element (sometimes called as 'swap and pop'). + // This modifies the order of the array, as noted in {at}. + + uint256 valueIndex = position - 1; + uint256 lastIndex = set._values.length - 1; + + if (valueIndex != lastIndex) { + bytes memory lastValue = set._values[lastIndex]; + + // Move the lastValue to the index where the value to delete is + set._values[valueIndex] = lastValue; + // Update the tracked position of the lastValue (that was just moved) + set._positions[lastValue] = position; + } + + // Delete the slot where the moved value was stored + set._values.pop(); + + // Delete the tracked position for the deleted slot + delete set._positions[value]; + + return true; + } else { + return false; + } + } + + /** + * @dev 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(BytesSet storage set) internal { + 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). + */ + function contains(BytesSet storage set, bytes memory value) internal view returns (bool) { + return set._positions[value] != 0; + } + + /** + * @dev Returns the number of values on the set. O(1). + */ + function length(BytesSet storage set) internal 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(BytesSet storage set, uint256 index) internal view returns (bytes memory) { + 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(BytesSet storage set) internal view returns (bytes[] memory) { + return set._values; + } + + /** + * @dev Return a slice of the 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(BytesSet storage set, uint256 start, uint256 end) internal view returns (bytes[] memory) { + unchecked { + end = Math.min(end, length(set)); + start = Math.min(start, end); + + uint256 len = end - start; + bytes[] memory result = new bytes[](len); + for (uint256 i = 0; i < len; ++i) { + result[i] = Arrays.unsafeAccess(set._values, start + i).value; + } + return result; + } + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/utils/structs/Heap.sol b/dependencies/@openzeppelin-contracts-5.4.0/utils/structs/Heap.sol new file mode 100644 index 00000000..c97bb432 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/utils/structs/Heap.sol @@ -0,0 +1,256 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.1.0) (utils/structs/Heap.sol) + +pragma solidity ^0.8.20; + +import {Math} from "../math/Math.sol"; +import {SafeCast} from "../math/SafeCast.sol"; +import {Comparators} from "../Comparators.sol"; +import {Arrays} from "../Arrays.sol"; +import {Panic} from "../Panic.sol"; +import {StorageSlot} from "../StorageSlot.sol"; + +/** + * @dev Library for managing https://en.wikipedia.org/wiki/Binary_heap[binary heap] that can be used as + * https://en.wikipedia.org/wiki/Priority_queue[priority queue]. + * + * Heaps are represented as a tree of values where the first element (index 0) is the root, and where the node at + * index i is the child of the node at index (i-1)/2 and the parent of nodes at index 2*i+1 and 2*i+2. Each node + * stores an element of the heap. + * + * The structure is ordered so that each node is bigger than its parent. An immediate consequence is that the + * highest priority value is the one at the root. This value can be looked up in constant time (O(1)) at + * `heap.tree[0]` + * + * The structure is designed to perform the following operations with the corresponding complexities: + * + * * peek (get the highest priority value): O(1) + * * insert (insert a value): O(log(n)) + * * pop (remove the highest priority value): O(log(n)) + * * replace (replace the highest priority value with a new value): O(log(n)) + * * length (get the number of elements): O(1) + * * clear (remove all elements): O(1) + * + * IMPORTANT: This library allows for the use of custom comparator functions. Given that manipulating + * memory can lead to unexpected behavior. Consider verifying that the comparator does not manipulate + * the Heap's state directly and that it follows the Solidity memory safety rules. + * + * _Available since v5.1._ + */ +library Heap { + using Arrays for *; + using Math for *; + using SafeCast for *; + + /** + * @dev Binary heap that supports values of type uint256. + * + * Each element of that structure uses one storage slot. + */ + struct Uint256Heap { + uint256[] tree; + } + + /** + * @dev Lookup the root element of the heap. + */ + function peek(Uint256Heap storage self) internal view returns (uint256) { + // self.tree[0] will `ARRAY_ACCESS_OUT_OF_BOUNDS` panic if heap is empty. + return self.tree[0]; + } + + /** + * @dev Remove (and return) the root element for the heap using the default comparator. + * + * NOTE: All inserting and removal from a heap should always be done using the same comparator. Mixing comparator + * during the lifecycle of a heap will result in undefined behavior. + */ + function pop(Uint256Heap storage self) internal returns (uint256) { + return pop(self, Comparators.lt); + } + + /** + * @dev Remove (and return) the root element for the heap using the provided comparator. + * + * NOTE: All inserting and removal from a heap should always be done using the same comparator. Mixing comparator + * during the lifecycle of a heap will result in undefined behavior. + */ + function pop( + Uint256Heap storage self, + function(uint256, uint256) view returns (bool) comp + ) internal returns (uint256) { + unchecked { + uint256 size = length(self); + if (size == 0) Panic.panic(Panic.EMPTY_ARRAY_POP); + + // cache + uint256 rootValue = self.tree.unsafeAccess(0).value; + uint256 lastValue = self.tree.unsafeAccess(size - 1).value; + + // swap last leaf with root, shrink tree and re-heapify + self.tree.pop(); + self.tree.unsafeAccess(0).value = lastValue; + _siftDown(self, size - 1, 0, lastValue, comp); + + return rootValue; + } + } + + /** + * @dev Insert a new element in the heap using the default comparator. + * + * NOTE: All inserting and removal from a heap should always be done using the same comparator. Mixing comparator + * during the lifecycle of a heap will result in undefined behavior. + */ + function insert(Uint256Heap storage self, uint256 value) internal { + insert(self, value, Comparators.lt); + } + + /** + * @dev Insert a new element in the heap using the provided comparator. + * + * NOTE: All inserting and removal from a heap should always be done using the same comparator. Mixing comparator + * during the lifecycle of a heap will result in undefined behavior. + */ + function insert( + Uint256Heap storage self, + uint256 value, + function(uint256, uint256) view returns (bool) comp + ) internal { + uint256 size = length(self); + + // push new item and re-heapify + self.tree.push(value); + _siftUp(self, size, value, comp); + } + + /** + * @dev Return the root element for the heap, and replace it with a new value, using the default comparator. + * This is equivalent to using {pop} and {insert}, but requires only one rebalancing operation. + * + * NOTE: All inserting and removal from a heap should always be done using the same comparator. Mixing comparator + * during the lifecycle of a heap will result in undefined behavior. + */ + function replace(Uint256Heap storage self, uint256 newValue) internal returns (uint256) { + return replace(self, newValue, Comparators.lt); + } + + /** + * @dev Return the root element for the heap, and replace it with a new value, using the provided comparator. + * This is equivalent to using {pop} and {insert}, but requires only one rebalancing operation. + * + * NOTE: All inserting and removal from a heap should always be done using the same comparator. Mixing comparator + * during the lifecycle of a heap will result in undefined behavior. + */ + function replace( + Uint256Heap storage self, + uint256 newValue, + function(uint256, uint256) view returns (bool) comp + ) internal returns (uint256) { + uint256 size = length(self); + if (size == 0) Panic.panic(Panic.EMPTY_ARRAY_POP); + + // cache + uint256 oldValue = self.tree.unsafeAccess(0).value; + + // replace and re-heapify + self.tree.unsafeAccess(0).value = newValue; + _siftDown(self, size, 0, newValue, comp); + + return oldValue; + } + + /** + * @dev Returns the number of elements in the heap. + */ + function length(Uint256Heap storage self) internal view returns (uint256) { + return self.tree.length; + } + + /** + * @dev Removes all elements in the heap. + */ + function clear(Uint256Heap storage self) internal { + self.tree.unsafeSetLength(0); + } + + /** + * @dev Swap node `i` and `j` in the tree. + */ + function _swap(Uint256Heap storage self, uint256 i, uint256 j) private { + StorageSlot.Uint256Slot storage ni = self.tree.unsafeAccess(i); + StorageSlot.Uint256Slot storage nj = self.tree.unsafeAccess(j); + (ni.value, nj.value) = (nj.value, ni.value); + } + + /** + * @dev Perform heap maintenance on `self`, starting at `index` (with the `value`), using `comp` as a + * comparator, and moving toward the leaves of the underlying tree. + * + * NOTE: This is a private function that is called in a trusted context with already cached parameters. `size` + * and `value` could be extracted from `self` and `index`, but that would require redundant storage read. These + * parameters are not verified. It is the caller role to make sure the parameters are correct. + */ + function _siftDown( + Uint256Heap storage self, + uint256 size, + uint256 index, + uint256 value, + function(uint256, uint256) view returns (bool) comp + ) private { + unchecked { + // Check if there is a risk of overflow when computing the indices of the child nodes. If that is the case, + // there cannot be child nodes in the tree, so sifting is done. + if (index >= type(uint256).max / 2) return; + + // Compute the indices of the potential child nodes + uint256 lIndex = 2 * index + 1; + uint256 rIndex = 2 * index + 2; + + // Three cases: + // 1. Both children exist: sifting may continue on one of the branch (selection required) + // 2. Only left child exist: sifting may continue on the left branch (no selection required) + // 3. Neither child exist: sifting is done + if (rIndex < size) { + uint256 lValue = self.tree.unsafeAccess(lIndex).value; + uint256 rValue = self.tree.unsafeAccess(rIndex).value; + if (comp(lValue, value) || comp(rValue, value)) { + uint256 cIndex = comp(lValue, rValue).ternary(lIndex, rIndex); + _swap(self, index, cIndex); + _siftDown(self, size, cIndex, value, comp); + } + } else if (lIndex < size) { + uint256 lValue = self.tree.unsafeAccess(lIndex).value; + if (comp(lValue, value)) { + _swap(self, index, lIndex); + _siftDown(self, size, lIndex, value, comp); + } + } + } + } + + /** + * @dev Perform heap maintenance on `self`, starting at `index` (with the `value`), using `comp` as a + * comparator, and moving toward the root of the underlying tree. + * + * NOTE: This is a private function that is called in a trusted context with already cached parameters. `value` + * could be extracted from `self` and `index`, but that would require redundant storage read. These parameters are not + * verified. It is the caller role to make sure the parameters are correct. + */ + function _siftUp( + Uint256Heap storage self, + uint256 index, + uint256 value, + function(uint256, uint256) view returns (bool) comp + ) private { + unchecked { + while (index > 0) { + uint256 parentIndex = (index - 1) / 2; + uint256 parentValue = self.tree.unsafeAccess(parentIndex).value; + if (comp(parentValue, value)) break; + _swap(self, index, parentIndex); + index = parentIndex; + } + } + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/utils/structs/MerkleTree.sol b/dependencies/@openzeppelin-contracts-5.4.0/utils/structs/MerkleTree.sol new file mode 100644 index 00000000..010ccfe8 --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/utils/structs/MerkleTree.sol @@ -0,0 +1,267 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.3.0) (utils/structs/MerkleTree.sol) + +pragma solidity ^0.8.20; + +import {Hashes} from "../cryptography/Hashes.sol"; +import {Arrays} from "../Arrays.sol"; +import {Panic} from "../Panic.sol"; +import {StorageSlot} from "../StorageSlot.sol"; + +/** + * @dev Library for managing https://wikipedia.org/wiki/Merkle_Tree[Merkle Tree] data structures. + * + * Each tree is a complete binary tree with the ability to sequentially insert leaves, changing them from a zero to a + * non-zero value and updating its root. This structure allows inserting commitments (or other entries) that are not + * stored, but can be proven to be part of the tree at a later time if the root is kept. See {MerkleProof}. + * + * A tree is defined by the following parameters: + * + * * Depth: The number of levels in the tree, it also defines the maximum number of leaves as 2**depth. + * * Zero value: The value that represents an empty leaf. Used to avoid regular zero values to be part of the tree. + * * Hashing function: A cryptographic hash function used to produce internal nodes. Defaults to {Hashes-commutativeKeccak256}. + * + * NOTE: Building trees using non-commutative hashing functions (i.e. `H(a, b) != H(b, a)`) is supported. However, + * proving the inclusion of a leaf in such trees is not possible with the {MerkleProof} library since it only supports + * _commutative_ hashing functions. + * + * _Available since v5.1._ + */ +library MerkleTree { + /// @dev Error emitted when trying to update a leaf that was not previously pushed. + error MerkleTreeUpdateInvalidIndex(uint256 index, uint256 length); + + /// @dev Error emitted when the proof used during an update is invalid (could not reproduce the side). + error MerkleTreeUpdateInvalidProof(); + + /** + * @dev A complete `bytes32` Merkle tree. + * + * The `sides` and `zero` arrays are set to have a length equal to the depth of the tree during setup. + * + * Struct members have an underscore prefix indicating that they are "private" and should not be read or written to + * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and + * lead to unexpected behavior. + * + * NOTE: The `root` and the updates history is not stored within the tree. Consider using a secondary structure to + * store a list of historical roots from the values returned from {setup} and {push} (e.g. a mapping, {BitMaps} or + * {Checkpoints}). + * + * WARNING: Updating any of the tree's parameters after the first insertion will result in a corrupted tree. + */ + struct Bytes32PushTree { + uint256 _nextLeafIndex; + bytes32[] _sides; + bytes32[] _zeros; + } + + /** + * @dev Initialize a {Bytes32PushTree} using {Hashes-commutativeKeccak256} to hash internal nodes. + * The capacity of the tree (i.e. number of leaves) is set to `2**treeDepth`. + * + * Calling this function on MerkleTree that was already setup and used will reset it to a blank state. + * + * Once a tree is setup, any push to it must use the same hashing function. This means that values + * should be pushed to it using the default {xref-MerkleTree-push-struct-MerkleTree-Bytes32PushTree-bytes32-}[push] function. + * + * IMPORTANT: The zero value should be carefully chosen since it will be stored in the tree representing + * empty leaves. It should be a value that is not expected to be part of the tree. + */ + function setup(Bytes32PushTree storage self, uint8 treeDepth, bytes32 zero) internal returns (bytes32 initialRoot) { + return setup(self, treeDepth, zero, Hashes.commutativeKeccak256); + } + + /** + * @dev Same as {xref-MerkleTree-setup-struct-MerkleTree-Bytes32PushTree-uint8-bytes32-}[setup], but allows to specify a custom hashing function. + * + * Once a tree is setup, any push to it must use the same hashing function. This means that values + * should be pushed to it using the custom push function, which should be the same one as used during the setup. + * + * IMPORTANT: Providing a custom hashing function is a security-sensitive operation since it may + * compromise the soundness of the tree. + * + * NOTE: Consider verifying that the hashing function does not manipulate the memory state directly and that it + * follows the Solidity memory safety rules. Otherwise, it may lead to unexpected behavior. + */ + function setup( + Bytes32PushTree storage self, + uint8 treeDepth, + bytes32 zero, + function(bytes32, bytes32) view returns (bytes32) fnHash + ) internal returns (bytes32 initialRoot) { + // Store depth in the dynamic array + Arrays.unsafeSetLength(self._sides, treeDepth); + Arrays.unsafeSetLength(self._zeros, treeDepth); + + // Build each root of zero-filled subtrees + bytes32 currentZero = zero; + for (uint256 i = 0; i < treeDepth; ++i) { + Arrays.unsafeAccess(self._zeros, i).value = currentZero; + currentZero = fnHash(currentZero, currentZero); + } + + // Set the first root + self._nextLeafIndex = 0; + + return currentZero; + } + + /** + * @dev Insert a new leaf in the tree, and compute the new root. Returns the position of the inserted leaf in the + * tree, and the resulting root. + * + * Hashing the leaf before calling this function is recommended as a protection against + * second pre-image attacks. + * + * This variant uses {Hashes-commutativeKeccak256} to hash internal nodes. It should only be used on merkle trees + * that were setup using the same (default) hashing function (i.e. by calling + * {xref-MerkleTree-setup-struct-MerkleTree-Bytes32PushTree-uint8-bytes32-}[the default setup] function). + */ + function push(Bytes32PushTree storage self, bytes32 leaf) internal returns (uint256 index, bytes32 newRoot) { + return push(self, leaf, Hashes.commutativeKeccak256); + } + + /** + * @dev Insert a new leaf in the tree, and compute the new root. Returns the position of the inserted leaf in the + * tree, and the resulting root. + * + * Hashing the leaf before calling this function is recommended as a protection against + * second pre-image attacks. + * + * This variant uses a custom hashing function to hash internal nodes. It should only be called with the same + * function as the one used during the initial setup of the merkle tree. + */ + function push( + Bytes32PushTree storage self, + bytes32 leaf, + function(bytes32, bytes32) view returns (bytes32) fnHash + ) internal returns (uint256 index, bytes32 newRoot) { + // Cache read + uint256 treeDepth = depth(self); + + // Get leaf index + index = self._nextLeafIndex++; + + // Check if tree is full. + if (index >= 1 << treeDepth) { + Panic.panic(Panic.RESOURCE_ERROR); + } + + // Rebuild branch from leaf to root + uint256 currentIndex = index; + bytes32 currentLevelHash = leaf; + for (uint256 i = 0; i < treeDepth; i++) { + // Reaching the parent node, is currentLevelHash the left child? + bool isLeft = currentIndex % 2 == 0; + + // If so, next time we will come from the right, so we need to save it + if (isLeft) { + Arrays.unsafeAccess(self._sides, i).value = currentLevelHash; + } + + // Compute the current node hash by using the hash function + // with either its sibling (side) or the zero value for that level. + currentLevelHash = fnHash( + isLeft ? currentLevelHash : Arrays.unsafeAccess(self._sides, i).value, + isLeft ? Arrays.unsafeAccess(self._zeros, i).value : currentLevelHash + ); + + // Update node index + currentIndex >>= 1; + } + + return (index, currentLevelHash); + } + + /** + * @dev Change the value of the leaf at position `index` from `oldValue` to `newValue`. Returns the recomputed "old" + * root (before the update) and "new" root (after the update). The caller must verify that the reconstructed old + * root is the last known one. + * + * The `proof` must be an up-to-date inclusion proof for the leaf being updated. This means that this function is + * vulnerable to front-running. Any {push} or {update} operation (that changes the root of the tree) would render + * all "in flight" updates invalid. + * + * This variant uses {Hashes-commutativeKeccak256} to hash internal nodes. It should only be used on merkle trees + * that were setup using the same (default) hashing function (i.e. by calling + * {xref-MerkleTree-setup-struct-MerkleTree-Bytes32PushTree-uint8-bytes32-}[the default setup] function). + */ + function update( + Bytes32PushTree storage self, + uint256 index, + bytes32 oldValue, + bytes32 newValue, + bytes32[] memory proof + ) internal returns (bytes32 oldRoot, bytes32 newRoot) { + return update(self, index, oldValue, newValue, proof, Hashes.commutativeKeccak256); + } + + /** + * @dev Change the value of the leaf at position `index` from `oldValue` to `newValue`. Returns the recomputed "old" + * root (before the update) and "new" root (after the update). The caller must verify that the reconstructed old + * root is the last known one. + * + * The `proof` must be an up-to-date inclusion proof for the leaf being update. This means that this function is + * vulnerable to front-running. Any {push} or {update} operation (that changes the root of the tree) would render + * all "in flight" updates invalid. + * + * This variant uses a custom hashing function to hash internal nodes. It should only be called with the same + * function as the one used during the initial setup of the merkle tree. + */ + function update( + Bytes32PushTree storage self, + uint256 index, + bytes32 oldValue, + bytes32 newValue, + bytes32[] memory proof, + function(bytes32, bytes32) view returns (bytes32) fnHash + ) internal returns (bytes32 oldRoot, bytes32 newRoot) { + unchecked { + // Check index range + uint256 length = self._nextLeafIndex; + if (index >= length) revert MerkleTreeUpdateInvalidIndex(index, length); + + // Cache read + uint256 treeDepth = depth(self); + + // Workaround stack too deep + bytes32[] storage sides = self._sides; + + // This cannot overflow because: 0 <= index < length + uint256 lastIndex = length - 1; + uint256 currentIndex = index; + bytes32 currentLevelHashOld = oldValue; + bytes32 currentLevelHashNew = newValue; + for (uint32 i = 0; i < treeDepth; i++) { + bool isLeft = currentIndex % 2 == 0; + + lastIndex >>= 1; + currentIndex >>= 1; + + if (isLeft && currentIndex == lastIndex) { + StorageSlot.Bytes32Slot storage side = Arrays.unsafeAccess(sides, i); + if (side.value != currentLevelHashOld) revert MerkleTreeUpdateInvalidProof(); + side.value = currentLevelHashNew; + } + + bytes32 sibling = proof[i]; + currentLevelHashOld = fnHash( + isLeft ? currentLevelHashOld : sibling, + isLeft ? sibling : currentLevelHashOld + ); + currentLevelHashNew = fnHash( + isLeft ? currentLevelHashNew : sibling, + isLeft ? sibling : currentLevelHashNew + ); + } + return (currentLevelHashOld, currentLevelHashNew); + } + } + + /** + * @dev Tree's depth (set at initialization) + */ + function depth(Bytes32PushTree storage self) internal view returns (uint256) { + return self._zeros.length; + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/utils/types/Time.sol b/dependencies/@openzeppelin-contracts-5.4.0/utils/types/Time.sol new file mode 100644 index 00000000..a495932d --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/utils/types/Time.sol @@ -0,0 +1,133 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.1.0) (utils/types/Time.sol) + +pragma solidity ^0.8.20; + +import {Math} from "../math/Math.sol"; +import {SafeCast} from "../math/SafeCast.sol"; + +/** + * @dev This library provides helpers for manipulating time-related objects. + * + * It uses the following types: + * - `uint48` for timepoints + * - `uint32` for durations + * + * While the library doesn't provide specific types for timepoints and duration, it does provide: + * - a `Delay` type to represent duration that can be programmed to change value automatically at a given point + * - additional helper functions + */ +library Time { + using Time for *; + + /** + * @dev Get the block timestamp as a Timepoint. + */ + function timestamp() internal view returns (uint48) { + return SafeCast.toUint48(block.timestamp); + } + + /** + * @dev Get the block number as a Timepoint. + */ + function blockNumber() internal view returns (uint48) { + return SafeCast.toUint48(block.number); + } + + // ==================================================== Delay ===================================================== + /** + * @dev A `Delay` is a uint32 duration that can be programmed to change value automatically at a given point in the + * future. The "effect" timepoint describes when the transitions happens from the "old" value to the "new" value. + * This allows updating the delay applied to some operation while keeping some guarantees. + * + * In particular, the {update} function guarantees that if the delay is reduced, the old delay still applies for + * some time. For example if the delay is currently 7 days to do an upgrade, the admin should not be able to set + * the delay to 0 and upgrade immediately. If the admin wants to reduce the delay, the old delay (7 days) should + * still apply for some time. + * + * + * The `Delay` type is 112 bits long, and packs the following: + * + * ``` + * | [uint48]: effect date (timepoint) + * | | [uint32]: value before (duration) + * ↓ ↓ ↓ [uint32]: value after (duration) + * 0xAAAAAAAAAAAABBBBBBBBCCCCCCCC + * ``` + * + * NOTE: The {get} and {withUpdate} functions operate using timestamps. Block number based delays are not currently + * supported. + */ + type Delay is uint112; + + /** + * @dev Wrap a duration into a Delay to add the one-step "update in the future" feature + */ + function toDelay(uint32 duration) internal pure returns (Delay) { + return Delay.wrap(duration); + } + + /** + * @dev Get the value at a given timepoint plus the pending value and effect timepoint if there is a scheduled + * change after this timepoint. If the effect timepoint is 0, then the pending value should not be considered. + */ + function _getFullAt( + Delay self, + uint48 timepoint + ) private pure returns (uint32 valueBefore, uint32 valueAfter, uint48 effect) { + (valueBefore, valueAfter, effect) = self.unpack(); + return effect <= timepoint ? (valueAfter, 0, 0) : (valueBefore, valueAfter, effect); + } + + /** + * @dev Get the current value plus the pending value and effect timepoint if there is a scheduled change. If the + * effect timepoint is 0, then the pending value should not be considered. + */ + function getFull(Delay self) internal view returns (uint32 valueBefore, uint32 valueAfter, uint48 effect) { + return _getFullAt(self, timestamp()); + } + + /** + * @dev Get the current value. + */ + function get(Delay self) internal view returns (uint32) { + (uint32 delay, , ) = self.getFull(); + return delay; + } + + /** + * @dev Update a Delay object so that it takes a new duration after a timepoint that is automatically computed to + * enforce the old delay at the moment of the update. Returns the updated Delay object and the timestamp when the + * new delay becomes effective. + */ + function withUpdate( + Delay self, + uint32 newValue, + uint32 minSetback + ) internal view returns (Delay updatedDelay, uint48 effect) { + uint32 value = self.get(); + uint32 setback = uint32(Math.max(minSetback, value > newValue ? value - newValue : 0)); + effect = timestamp() + setback; + return (pack(value, newValue, effect), effect); + } + + /** + * @dev Split a delay into its components: valueBefore, valueAfter and effect (transition timepoint). + */ + function unpack(Delay self) internal pure returns (uint32 valueBefore, uint32 valueAfter, uint48 effect) { + uint112 raw = Delay.unwrap(self); + + valueAfter = uint32(raw); + valueBefore = uint32(raw >> 32); + effect = uint48(raw >> 64); + + return (valueBefore, valueAfter, effect); + } + + /** + * @dev pack the components into a Delay object. + */ + function pack(uint32 valueBefore, uint32 valueAfter, uint48 effect) internal pure returns (Delay) { + return Delay.wrap((uint112(effect) << 64) | (uint112(valueBefore) << 32) | uint112(valueAfter)); + } +} diff --git a/dependencies/@openzeppelin-contracts-5.4.0/vendor/compound/ICompoundTimelock.sol b/dependencies/@openzeppelin-contracts-5.4.0/vendor/compound/ICompoundTimelock.sol new file mode 100644 index 00000000..84cd62ed --- /dev/null +++ b/dependencies/@openzeppelin-contracts-5.4.0/vendor/compound/ICompoundTimelock.sol @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.4.0) (vendor/compound/ICompoundTimelock.sol) + +pragma solidity >=0.6.9; + +/** + * https://github.com/compound-finance/compound-protocol/blob/master/contracts/Timelock.sol[Compound timelock] interface + */ +interface ICompoundTimelock { + event NewAdmin(address indexed newAdmin); + event NewPendingAdmin(address indexed newPendingAdmin); + event NewDelay(uint256 indexed newDelay); + event CancelTransaction( + bytes32 indexed txHash, + address indexed target, + uint256 value, + string signature, + bytes data, + uint256 eta + ); + event ExecuteTransaction( + bytes32 indexed txHash, + address indexed target, + uint256 value, + string signature, + bytes data, + uint256 eta + ); + event QueueTransaction( + bytes32 indexed txHash, + address indexed target, + uint256 value, + string signature, + bytes data, + uint256 eta + ); + + receive() external payable; + + // solhint-disable-next-line func-name-mixedcase + function GRACE_PERIOD() external view returns (uint256); + + // solhint-disable-next-line func-name-mixedcase + function MINIMUM_DELAY() external view returns (uint256); + + // solhint-disable-next-line func-name-mixedcase + function MAXIMUM_DELAY() external view returns (uint256); + + function admin() external view returns (address); + + function pendingAdmin() external view returns (address); + + function delay() external view returns (uint256); + + function queuedTransactions(bytes32) external view returns (bool); + + function setDelay(uint256) external; + + function acceptAdmin() external; + + function setPendingAdmin(address) external; + + function queueTransaction( + address target, + uint256 value, + string memory signature, + bytes memory data, + uint256 eta + ) external returns (bytes32); + + function cancelTransaction( + address target, + uint256 value, + string memory signature, + bytes memory data, + uint256 eta + ) external; + + function executeTransaction( + address target, + uint256 value, + string memory signature, + bytes memory data, + uint256 eta + ) external payable returns (bytes memory); +} diff --git a/dependencies/a16z-halmos-cheatcodes-6da4e692c357ba6d641a2e677a28298cac9f76ab/LICENSE b/dependencies/a16z-halmos-cheatcodes-6da4e692c357ba6d641a2e677a28298cac9f76ab/LICENSE new file mode 100644 index 00000000..0ad25db4 --- /dev/null +++ b/dependencies/a16z-halmos-cheatcodes-6da4e692c357ba6d641a2e677a28298cac9f76ab/LICENSE @@ -0,0 +1,661 @@ + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + + A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + + The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + + An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU Affero General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Remote Network Interaction; Use with the GNU General Public License. + + Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the work with which it is combined will remain governed by version +3 of the GNU General Public License. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU Affero General Public License from time to time. Such new versions +will be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU Affero General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU Affero General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU Affero General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a "Source" link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for the +specific requirements. + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU AGPL, see +. diff --git a/dependencies/a16z-halmos-cheatcodes-6da4e692c357ba6d641a2e677a28298cac9f76ab/README.md b/dependencies/a16z-halmos-cheatcodes-6da4e692c357ba6d641a2e677a28298cac9f76ab/README.md new file mode 100644 index 00000000..209c2cfa --- /dev/null +++ b/dependencies/a16z-halmos-cheatcodes-6da4e692c357ba6d641a2e677a28298cac9f76ab/README.md @@ -0,0 +1,97 @@ +# Halmos Cheat Codes + +Halmos cheatcodes are abstract functions designed to facilitate writing symbolic tests, such as the creation of new symbolic values at runtime. While these cheatcodes are currently exclusive to [Halmos][halmos], they are not limited to it and could potentially be supported by other symbolic testing tools in the future. + +Please refer to [the list of currently available cheatcodes][list]. More cheatcodes will be added in the future. + +Join the [Halmos Telegram Group][chat] for any inquiries or further discussions. + +[halmos]: +[list]: +[chat]: + +## Installation + +To install using Foundry: +``` +forge install a16z/halmos-cheatcodes +``` +Alternatively, you can directly add it as a submodule: +``` +git submodule add https://github.com/a16z/halmos-cheatcodes +``` + +## Example usage + +Below is an example of a symbolic test that checks for potential unauthorized access to others' tokens. The approach involves setting up an initial symbolic state of the token contract, executing an arbitrary function call to the token contract, and checking if there is an execution path that increases the caller's balance and/or decreases the balance of others. This example illustrates how to utilize cheatcodes to set up initial symbolic states and execute arbitrary function calls. + +```solidity +// import Halmos cheatcodes +import {SymTest} from "halmos-cheatcodes/SymTest.sol"; + +import {Test} from "forge-std/Test.sol"; + +import {Token} from "/path/to/Token.sol"; + +contract TokenTest is SymTest, Test { + Token token; + + function setUp() public { + token = new Token(); + + // set the balances of three arbitrary accounts to arbitrary symbolic values + for (uint256 i = 0; i < 3; i++) { + address receiver = svm.createAddress('receiver'); // create a new symbolic address + uint256 amount = svm.createUint256('amount'); // create a new symbolic uint256 value + token.transfer(receiver, amount); + } + } + + function checkBalanceUpdate() public { + // consider two arbitrary distinct accounts + address caller = svm.createAddress('caller'); // create a symbolic address + address others = svm.createAddress('others'); // create another symbolic address + vm.assume(others != caller); // assume the two addresses are different + + // record their current balances + uint256 oldBalanceCaller = token.balanceOf(caller); + uint256 oldBalanceOthers = token.balanceOf(others); + + // execute an arbitrary function call to the token from the caller + vm.prank(caller); + uint256 dataSize = 100; // the max calldata size for the public functions in the token + bytes memory data = svm.createBytes(dataSize, 'data'); // create a symbolic calldata + address(token).call(data); + + // ensure that the caller cannot spend others' tokens + assert(token.balanceOf(caller) <= oldBalanceCaller); // cannot increase their own balance + assert(token.balanceOf(others) >= oldBalanceOthers); // cannot decrease others' balance + } +} +``` + +When running the above test against the following buggy token contract, Halmos will provide a counterexample that may be overlooked during manual reviews. + +```solidity +/// @notice This is a buggy token contract. DO NOT use it in production. +contract Token { + mapping(address => uint) public balanceOf; + + constructor() public { + balanceOf[msg.sender] = 1e27; + } + + function transfer(address to, uint amount) public { + _transfer(msg.sender, to, amount); + } + + function _transfer(address from, address to, uint amount) public { + balanceOf[from] -= amount; + balanceOf[to] += amount; + } +} +``` + +## Disclaimer + +_These smart contracts and code are being provided as is. No guarantee, representation or warranty is being made, express or implied, as to the safety or correctness of the user interface or the smart contracts and code. They have not been audited and as such there can be no assurance they will work as intended, and users may experience delays, failures, errors, omissions or loss of transmitted information. THE SMART CONTRACTS AND CODE CONTAINED HEREIN ARE FURNISHED AS IS, WHERE IS, WITH ALL FAULTS AND WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING ANY WARRANTY OF MERCHANTABILITY, NON-INFRINGEMENT OR FITNESS FOR ANY PARTICULAR PURPOSE. Further, use of any of these smart contracts and code may be restricted or prohibited under applicable law, including securities laws, and it is therefore strongly advised for you to contact a reputable attorney in any jurisdiction where these smart contracts and code may be accessible for any questions or concerns with respect thereto. Further, no information provided in this repo should be construed as investment advice or legal advice for any particular facts or circumstances, and is not meant to replace competent counsel. a16z is not liable for any use of the foregoing, and users should proceed with caution and use at their own risk. See a16z.com/disclosures for more info._ diff --git a/dependencies/a16z-halmos-cheatcodes-6da4e692c357ba6d641a2e677a28298cac9f76ab/src/SVM.sol b/dependencies/a16z-halmos-cheatcodes-6da4e692c357ba6d641a2e677a28298cac9f76ab/src/SVM.sol new file mode 100644 index 00000000..5e435ccb --- /dev/null +++ b/dependencies/a16z-halmos-cheatcodes-6da4e692c357ba6d641a2e677a28298cac9f76ab/src/SVM.sol @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: AGPL-3.0 +pragma solidity >=0.8.0 <0.9.0; + +/// @notice Symbolic Virtual Machine +interface SVM { + // Create a new symbolic uint value ranging over [0, 2**bitSize - 1] (inclusive) + function createUint(uint256 bitSize, string memory name) external pure returns (uint256 value); + + // Create a new symbolic uint256 value + function createUint256(string memory name) external pure returns (uint256 value); + + // Create a new symbolic signed int value + function createInt(uint256 bitSize, string memory name) external pure returns (int256 value); + + // Create a new symbolic int256 value + function createInt256(string memory name) external pure returns (int256 value); + + // Create a new symbolic byte array with the given byte size + function createBytes(uint256 byteSize, string memory name) external pure returns (bytes memory value); + + // Create a new symbolic string backed by a symbolic array with the given byte size + function createString(uint256 byteSize, string memory name) external pure returns (string memory value); + + // Create a new symbolic bytes32 value + function createBytes32(string memory name) external pure returns (bytes32 value); + + // Create a new symbolic bytes4 value + function createBytes4(string memory name) external pure returns (bytes4 value); + + // Create a new symbolic address value + function createAddress(string memory name) external pure returns (address value); + + // Create a new symbolic boolean value + function createBool(string memory name) external pure returns (bool value); + + // Create arbitrary symbolic calldata for the given contract address, name, or interface name. + // An exception is thrown if the contract name is not found or is ambiguous across multiple files. An optional filename (with .sol extension) can be provided to avoid ambiguity. + // By default, view and pure functions are excluded. An optional boolean flag can be set to include view and pure functions. + function createCalldata(address contractAddress) external pure returns (bytes memory data); + function createCalldata(address contractAddress, bool includeViewAndPureFunctions) external pure returns (bytes memory data); + function createCalldata(string memory contractOrInterfaceName) external pure returns (bytes memory data); + function createCalldata(string memory contractOrInterfaceName, bool includeViewAndPureFunctions) external pure returns (bytes memory data); + function createCalldata(string memory filename, string memory contractOrInterfaceName) external pure returns (bytes memory data); + function createCalldata(string memory filename, string memory contractOrInterfaceName, bool includeViewAndPureFunctions) external pure returns (bytes memory data); + + // Assign symbolic values to uninitialized storage slots + function enableSymbolicStorage(address) external; + + // Snapshot the current storage of the given account and return a snapshot ID + function snapshotStorage(address) external returns (uint256 id); +} diff --git a/dependencies/a16z-halmos-cheatcodes-6da4e692c357ba6d641a2e677a28298cac9f76ab/src/SymTest.sol b/dependencies/a16z-halmos-cheatcodes-6da4e692c357ba6d641a2e677a28298cac9f76ab/src/SymTest.sol new file mode 100644 index 00000000..96684ed8 --- /dev/null +++ b/dependencies/a16z-halmos-cheatcodes-6da4e692c357ba6d641a2e677a28298cac9f76ab/src/SymTest.sol @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: AGPL-3.0 +pragma solidity >=0.8.0 <0.9.0; + +import {SVM} from "./SVM.sol"; + +abstract contract SymTest { + // SVM cheat code address: 0xf3993a62377bcd56ae39d773740a5390411e8bc9 + address internal constant SVM_ADDRESS = address(uint160(uint256(keccak256("svm cheat code")))); + + SVM internal constant svm = SVM(SVM_ADDRESS); +} diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/.depcheckrc b/dependencies/eth-infinitism-account-abstraction-0.8.0/.depcheckrc new file mode 100644 index 00000000..942eed55 --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/.depcheckrc @@ -0,0 +1 @@ +ignores: ["@openzeppelin/contracts", "@uniswap/v3-periphery", " @typechain/ethers-v5" ] diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/.eslintrc.js b/dependencies/eth-infinitism-account-abstraction-0.8.0/.eslintrc.js new file mode 100644 index 00000000..fde1d6d6 --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/.eslintrc.js @@ -0,0 +1,79 @@ +module.exports = { + env: { + browser: true, + es6: true, + jest: true, + mocha: true, + node: true + }, + globals: { + artifacts: false, + assert: false, + contract: false, + web3: false + }, + extends: + [ + 'standard-with-typescript' + ], + // This is needed to add configuration to rules with type information + parser: '@typescript-eslint/parser', + parserOptions: { + project: ['./tsconfig.json'] + }, + ignorePatterns: [ + '.eslintrc.js', + '**/types/truffle-contracts', + 'coverage', + 'dist/' + ], + rules: { + 'no-console': 'off', + '@typescript-eslint/no-var-requires': 'off', + '@typescript-eslint/return-await': 'off', + '@typescript-eslint/no-unnecessary-type-assertion': 'off', + '@typescript-eslint/require-array-sort-compare': ['error', + { + ignoreStringArrays: true + } + ] + }, + overrides: [ + { + files: '*', + rules: { + '@typescript-eslint/naming-convention': 'off', + '@typescript-eslint/no-non-null-assertion': 'off', + '@typescript-eslint/restrict-template-expressions': 'off' + } + }, + { + files: [ + '**/test/**/*.ts' + ], + rules: { + 'no-unused-expressions': 'off', + // chai assertions trigger this rule + '@typescript-eslint/no-unused-expressions': 'off', + '@typescript-eslint/no-non-null-assertion': 'off' + } + }, + { + // otherwise it will raise an error in every JavaScript file + files: ['*.ts'], + rules: { + '@typescript-eslint/prefer-ts-expect-error': 'off', + // allow using '${val}' with numbers, bool and null types + '@typescript-eslint/restrict-template-expressions': [ + 'error', + { + allowNumber: true, + allowBoolean: true, + allowNullish: true, + allowNullable: true + } + ] + } + } + ] +} diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/.github/workflows/build.yml b/dependencies/eth-infinitism-account-abstraction-0.8.0/.github/workflows/build.yml new file mode 100644 index 00000000..2d8896ce --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/.github/workflows/build.yml @@ -0,0 +1,93 @@ +name: Build +on: + push: + branches: + - '*' + pull_request: + types: [opened, reopened, synchronize] + +env: + TS_NODE_TRANSPILE_ONLY: 1 + FORCE_COLORS: 1 + +# todo: extract shared seto/checkout/install/compile, instead of repeat in each job. +jobs: + + test: + runs-on: ubuntu-latest + + steps: + - uses: actions/setup-node@v4 + with: + node-version: '22' + - uses: actions/checkout@v4 + - uses: actions/cache@v4 + with: + path: node_modules + key: ${{ runner.os }}-${{ hashFiles('yarn.lock') }} + - run: yarn install + - run: yarn compile + - run: yarn tsc + + - run: yarn run ci + + gas-checks: + runs-on: ubuntu-latest + + steps: + - uses: actions/setup-node@v4 + with: + node-version: '22' + - uses: actions/checkout@v4 + with: + show-progress: false + - uses: actions/cache@v4 + with: + path: node_modules + key: ${{ runner.os }}-${{ hashFiles('yarn.lock') }} + - run: yarn install + - run: yarn compile + - run: yarn ci-gas-calc + + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/setup-node@v4 + with: + node-version: '22' + - uses: actions/checkout@v4 + with: + show-progress: false + - uses: actions/cache@v4 + with: + path: node_modules + key: ${{ runner.os }}-${{ hashFiles('yarn.lock') }} + - run: yarn install + - run: yarn depcheck + - run: yarn lint + + coverage: + runs-on: ubuntu-latest + steps: + - uses: actions/setup-node@v4 + with: + node-version: '22' + - uses: actions/checkout@v4 + with: + show-progress: false + - uses: actions/cache@v4 + with: + path: node_modules + key: ${{ runner.os }}-${{ hashFiles('yarn.lock') }} + - run: yarn install + + - run: yarn compile + + - run: FORCE_COLOR=1 yarn coverage + - uses: actions/upload-artifact@v4 + with: + name: solidity-coverage + path: | + coverage/ + coverage.json + diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/.gitignore b/dependencies/eth-infinitism-account-abstraction-0.8.0/.gitignore new file mode 100644 index 00000000..f6a4ff52 --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/.gitignore @@ -0,0 +1,20 @@ +node_modules + +#Hardhat files +cache +artifacts +/.idea/ +/typechain/ +/dist/ +/yarn-error.log +/deployments/dev/ +/deployments/localhost/ +/deployments/proxy/ +/typechain-types/ +/reports/gas-used-output.color +/coverage +/coverage.json +/.DS_Store +.DS_Store +/contracts/dist/ +/contracts/types/ diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/.solcover.js b/dependencies/eth-infinitism-account-abstraction-0.8.0/.solcover.js new file mode 100644 index 00000000..133010a9 --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/.solcover.js @@ -0,0 +1,8 @@ +module.exports = { + skipFiles: [ + "test", + "utils/Exec.sol", + "samples" + ], + configureYulOptimizer: true, +}; diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/.solhint.json b/dependencies/eth-infinitism-account-abstraction-0.8.0/.solhint.json new file mode 100644 index 00000000..2b5dda04 --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/.solhint.json @@ -0,0 +1,12 @@ +{ + "extends": "solhint:recommended", + "rules": { + "compiler-version": ["error",">=0.7.5"], + "func-visibility": ["off",{"ignoreConstructors":true}], + "custom-errors": ["off"], + "explicit-types": ["warn", "explicit"], + "no-global-import": ["off"], + "immutable-vars-naming": ["off"], + "mark-callable-contracts": ["off"] + } +} diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/.solhintignore b/dependencies/eth-infinitism-account-abstraction-0.8.0/.solhintignore new file mode 100644 index 00000000..4972aa1b --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/.solhintignore @@ -0,0 +1 @@ +contracts/samples/bls/lib/ diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/LICENSE b/dependencies/eth-infinitism-account-abstraction-0.8.0/LICENSE new file mode 100644 index 00000000..f288702d --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/README.md b/dependencies/eth-infinitism-account-abstraction-0.8.0/README.md new file mode 100644 index 00000000..57216f82 --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/README.md @@ -0,0 +1,11 @@ +Implementation of contracts for [ERC-4337](https://eips.ethereum.org/EIPS/eip-4337) account abstraction via alternative mempool. + +# Resources + +[Vitalik's post on account abstraction without Ethereum protocol changes](https://medium.com/infinitism/erc-4337-account-abstraction-without-ethereum-protocol-changes-d75c9d94dc4a) + +[Discord server](http://discord.gg/fbDyENb6Y9) + +[Bundler reference implementation](https://github.com/eth-infinitism/bundler) + +[Bundler specification test suite](https://github.com/eth-infinitism/bundler-spec-tests) diff --git "a/dependencies/eth-infinitism-account-abstraction-0.8.0/audits/EIP_4337_\342\200\223_Ethereum_Account_Abstraction_Incremental_Audit_Feb_2023.pdf" "b/dependencies/eth-infinitism-account-abstraction-0.8.0/audits/EIP_4337_\342\200\223_Ethereum_Account_Abstraction_Incremental_Audit_Feb_2023.pdf" new file mode 100644 index 0000000000000000000000000000000000000000..7050f47a62451a663f848fcd4c989435cef7ff65 GIT binary patch literal 565821 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�JM%*sE60Juv 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
!!QOC)WIW?Wws8T3Z)P?}OrAd=IJJn_=@ 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¬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 Cz~0mV literal 0 HcmV?d00001 diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/audits/ERC-4337 Account Abstraction Incremental Audit Report Feb 20 2024.pdf b/dependencies/eth-infinitism-account-abstraction-0.8.0/audits/ERC-4337 Account Abstraction Incremental Audit Report Feb 20 2024.pdf new file mode 100644 index 0000000000000000000000000000000000000000..4bcb24a1f062dc3db28de4a44b4b2707fc45949d GIT binary patch literal 243905 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 z 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 gXzI_ZswlW$Bs?Y(90btS*WI;C0#sG49IXL=1Ig 0) { + return SimpleAccount(payable(addr)); + } + ret = SimpleAccount(payable(new ERC1967Proxy{salt : bytes32(salt)}( + address(accountImplementation), + abi.encodeCall(SimpleAccount.initialize, (owner)) + ))); + } + + /** + * calculate the counterfactual address of this account as it would be returned by createAccount() + */ + function getAddress(address owner,uint256 salt) public view returns (address) { + return Create2.computeAddress(bytes32(salt), keccak256(abi.encodePacked( + type(ERC1967Proxy).creationCode, + abi.encode( + address(accountImplementation), + abi.encodeCall(SimpleAccount.initialize, (owner)) + ) + ))); + } +} diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/accounts/callback/TokenCallbackHandler.sol b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/accounts/callback/TokenCallbackHandler.sol new file mode 100644 index 00000000..06251ae0 --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/accounts/callback/TokenCallbackHandler.sol @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.28; + +/* solhint-disable no-empty-blocks */ + +import "@openzeppelin/contracts/utils/introspection/IERC165.sol"; +import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol"; +import "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol"; + +/** + * Token callback handler. + * Handles supported tokens' callbacks, allowing account receiving these tokens. + */ +abstract contract TokenCallbackHandler is IERC721Receiver, IERC1155Receiver { + + function onERC721Received( + address, + address, + uint256, + bytes calldata + ) external pure override returns (bytes4) { + return IERC721Receiver.onERC721Received.selector; + } + + function onERC1155Received( + address, + address, + uint256, + uint256, + bytes calldata + ) external pure override returns (bytes4) { + return IERC1155Receiver.onERC1155Received.selector; + } + + function onERC1155BatchReceived( + address, + address, + uint256[] calldata, + uint256[] calldata, + bytes calldata + ) external pure override returns (bytes4) { + return IERC1155Receiver.onERC1155BatchReceived.selector; + } + + function supportsInterface(bytes4 interfaceId) external view virtual override returns (bool) { + return + interfaceId == type(IERC721Receiver).interfaceId || + interfaceId == type(IERC1155Receiver).interfaceId || + interfaceId == type(IERC165).interfaceId; + } +} diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/BaseAccount.sol b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/BaseAccount.sol new file mode 100644 index 00000000..60d0ccd1 --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/BaseAccount.sol @@ -0,0 +1,161 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.28; + +/* solhint-disable avoid-low-level-calls */ +/* solhint-disable no-empty-blocks */ +/* solhint-disable no-inline-assembly */ + +import "../interfaces/IAccount.sol"; +import "../interfaces/IEntryPoint.sol"; +import "../utils/Exec.sol"; +import "./UserOperationLib.sol"; + +/** + * Basic account implementation. + * This contract provides the basic logic for implementing the IAccount interface - validateUserOp + * Specific account implementation should inherit it and provide the account-specific logic. + */ +abstract contract BaseAccount is IAccount { + using UserOperationLib for PackedUserOperation; + + struct Call { + address target; + uint256 value; + bytes data; + } + + error ExecuteError(uint256 index, bytes error); + + /** + * Return the account nonce. + * This method returns the next sequential nonce. + * For a nonce of a specific key, use `entrypoint.getNonce(account, key)` + */ + function getNonce() public view virtual returns (uint256) { + return entryPoint().getNonce(address(this), 0); + } + + /** + * Return the entryPoint used by this account. + * Subclass should return the current entryPoint used by this account. + */ + function entryPoint() public view virtual returns (IEntryPoint); + + /** + * execute a single call from the account. + */ + function execute(address target, uint256 value, bytes calldata data) virtual external { + _requireForExecute(); + + bool ok = Exec.call(target, value, data, gasleft()); + if (!ok) { + Exec.revertWithReturnData(); + } + } + + /** + * execute a batch of calls. + * revert on the first call that fails. + * If the batch reverts, and it contains more than a single call, then wrap the revert with ExecuteError, + * to mark the failing call index. + */ + function executeBatch(Call[] calldata calls) virtual external { + _requireForExecute(); + + uint256 callsLength = calls.length; + for (uint256 i = 0; i < callsLength; i++) { + Call calldata call = calls[i]; + bool ok = Exec.call(call.target, call.value, call.data, gasleft()); + if (!ok) { + if (callsLength == 1) { + Exec.revertWithReturnData(); + } else { + revert ExecuteError(i, Exec.getReturnData(0)); + } + } + } + } + + /// @inheritdoc IAccount + function validateUserOp( + PackedUserOperation calldata userOp, + bytes32 userOpHash, + uint256 missingAccountFunds + ) external virtual override returns (uint256 validationData) { + _requireFromEntryPoint(); + validationData = _validateSignature(userOp, userOpHash); + _validateNonce(userOp.nonce); + _payPrefund(missingAccountFunds); + } + + /** + * Ensure the request comes from the known entrypoint. + */ + function _requireFromEntryPoint() internal view virtual { + require( + msg.sender == address(entryPoint()), + "account: not from EntryPoint" + ); + } + + function _requireForExecute() internal view virtual { + _requireFromEntryPoint(); + } + + /** + * Validate the signature is valid for this message. + * @param userOp - Validate the userOp.signature field. + * @param userOpHash - Convenient field: the hash of the request, to check the signature against. + * (also hashes the entrypoint and chain id) + * @return validationData - Signature and time-range of this operation. + * <20-byte> aggregatorOrSigFail - 0 for valid signature, 1 to mark signature failure, + * otherwise, an address of an aggregator contract. + * <6-byte> validUntil - Last timestamp this operation is valid at, or 0 for "indefinitely" + * <6-byte> validAfter - first timestamp this operation is valid + * If the account doesn't use time-range, it is enough to return + * SIG_VALIDATION_FAILED value (1) for signature failure. + * Note that the validation code cannot use block.timestamp (or block.number) directly. + */ + function _validateSignature( + PackedUserOperation calldata userOp, + bytes32 userOpHash + ) internal virtual returns (uint256 validationData); + + /** + * Validate the nonce of the UserOperation. + * This method may validate the nonce requirement of this account. + * e.g. + * To limit the nonce to use sequenced UserOps only (no "out of order" UserOps): + * `require(nonce < type(uint64).max)` + * For a hypothetical account that *requires* the nonce to be out-of-order: + * `require(nonce & type(uint64).max == 0)` + * + * The actual nonce uniqueness is managed by the EntryPoint, and thus no other + * action is needed by the account itself. + * + * @param nonce to validate + * + * solhint-disable-next-line no-empty-blocks + */ + function _validateNonce(uint256 nonce) internal view virtual { + } + + /** + * Sends to the entrypoint (msg.sender) the missing funds for this transaction. + * SubClass MAY override this method for better funds management + * (e.g. send to the entryPoint more than the minimum required, so that in future transactions + * it will not be required to send again). + * @param missingAccountFunds - The minimum value this method should send the entrypoint. + * This value MAY be zero, in case there is enough deposit, + * or the userOp has a paymaster. + */ + function _payPrefund(uint256 missingAccountFunds) internal virtual { + if (missingAccountFunds != 0) { + (bool success,) = payable(msg.sender).call{ + value: missingAccountFunds + }(""); + (success); + // Ignore failure (its EntryPoint's job to verify, not account.) + } + } +} diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/BasePaymaster.sol b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/BasePaymaster.sol new file mode 100644 index 00000000..dfaf555d --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/BasePaymaster.sol @@ -0,0 +1,151 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.28; + +/* solhint-disable reason-string */ + +import "@openzeppelin/contracts/access/Ownable2Step.sol"; +import "@openzeppelin/contracts/utils/introspection/IERC165.sol"; +import "../interfaces/IPaymaster.sol"; +import "../interfaces/IEntryPoint.sol"; +import "./UserOperationLib.sol"; +/** + * Helper class for creating a paymaster. + * provides helper methods for staking. + * Validates that the postOp is called only by the entryPoint. + */ +abstract contract BasePaymaster is IPaymaster, Ownable2Step { + IEntryPoint public immutable entryPoint; + + uint256 internal constant PAYMASTER_VALIDATION_GAS_OFFSET = UserOperationLib.PAYMASTER_VALIDATION_GAS_OFFSET; + uint256 internal constant PAYMASTER_POSTOP_GAS_OFFSET = UserOperationLib.PAYMASTER_POSTOP_GAS_OFFSET; + uint256 internal constant PAYMASTER_DATA_OFFSET = UserOperationLib.PAYMASTER_DATA_OFFSET; + + constructor(IEntryPoint _entryPoint) Ownable(msg.sender) { + _validateEntryPointInterface(_entryPoint); + entryPoint = _entryPoint; + } + + // Sanity check: make sure this EntryPoint was compiled against the same + // IEntryPoint of this paymaster + function _validateEntryPointInterface(IEntryPoint _entryPoint) internal virtual { + require(IERC165(address(_entryPoint)).supportsInterface(type(IEntryPoint).interfaceId), "IEntryPoint interface mismatch"); + } + + /// @inheritdoc IPaymaster + function validatePaymasterUserOp( + PackedUserOperation calldata userOp, + bytes32 userOpHash, + uint256 maxCost + ) external override returns (bytes memory context, uint256 validationData) { + _requireFromEntryPoint(); + return _validatePaymasterUserOp(userOp, userOpHash, maxCost); + } + + /** + * Validate a user operation. + * @param userOp - The user operation. + * @param userOpHash - The hash of the user operation. + * @param maxCost - The maximum cost of the user operation. + */ + function _validatePaymasterUserOp( + PackedUserOperation calldata userOp, + bytes32 userOpHash, + uint256 maxCost + ) internal virtual returns (bytes memory context, uint256 validationData); + + /// @inheritdoc IPaymaster + function postOp( + PostOpMode mode, + bytes calldata context, + uint256 actualGasCost, + uint256 actualUserOpFeePerGas + ) external override { + _requireFromEntryPoint(); + _postOp(mode, context, actualGasCost, actualUserOpFeePerGas); + } + + /** + * Post-operation handler. + * (verified to be called only through the entryPoint) + * @dev If subclass returns a non-empty context from validatePaymasterUserOp, + * it must also implement this method. + * @param mode - Enum with the following options: + * opSucceeded - User operation succeeded. + * opReverted - User op reverted. The paymaster still has to pay for gas. + * postOpReverted - never passed in a call to postOp(). + * @param context - The context value returned by validatePaymasterUserOp + * @param actualGasCost - Actual cost of gas used so far (without this postOp call). + * @param actualUserOpFeePerGas - the gas price this UserOp pays. This value is based on the UserOp's maxFeePerGas + * and maxPriorityFee (and basefee) + * It is not the same as tx.gasprice, which is what the bundler pays. + */ + function _postOp( + PostOpMode mode, + bytes calldata context, + uint256 actualGasCost, + uint256 actualUserOpFeePerGas + ) internal virtual { + (mode, context, actualGasCost, actualUserOpFeePerGas); // unused params + // subclass must override this method if validatePaymasterUserOp returns a context + revert("must override"); + } + + /** + * Add a deposit for this paymaster, used for paying for transaction fees. + */ + function deposit() public payable { + entryPoint.depositTo{value: msg.value}(address(this)); + } + + /** + * Withdraw value from the deposit. + * @param withdrawAddress - Target to send to. + * @param amount - Amount to withdraw. + */ + function withdrawTo( + address payable withdrawAddress, + uint256 amount + ) public onlyOwner { + entryPoint.withdrawTo(withdrawAddress, amount); + } + + /** + * Add stake for this paymaster. + * This method can also carry eth value to add to the current stake. + * @param unstakeDelaySec - The unstake delay for this paymaster. Can only be increased. + */ + function addStake(uint32 unstakeDelaySec) external payable onlyOwner { + entryPoint.addStake{value: msg.value}(unstakeDelaySec); + } + + /** + * Return current paymaster's deposit on the entryPoint. + */ + function getDeposit() public view returns (uint256) { + return entryPoint.balanceOf(address(this)); + } + + /** + * Unlock the stake, in order to withdraw it. + * The paymaster can't serve requests once unlocked, until it calls addStake again + */ + function unlockStake() external onlyOwner { + entryPoint.unlockStake(); + } + + /** + * Withdraw the entire paymaster's stake. + * stake must be unlocked first (and then wait for the unstakeDelay to be over) + * @param withdrawAddress - The address to send withdrawn value. + */ + function withdrawStake(address payable withdrawAddress) external onlyOwner { + entryPoint.withdrawStake(withdrawAddress); + } + + /** + * Validate the call is made from a valid entrypoint + */ + function _requireFromEntryPoint() internal virtual { + require(msg.sender == address(entryPoint), "Sender not EntryPoint"); + } +} diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/Eip7702Support.sol b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/Eip7702Support.sol new file mode 100644 index 00000000..bf8e035c --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/Eip7702Support.sol @@ -0,0 +1,81 @@ +pragma solidity ^0.8.28; +// SPDX-License-Identifier: MIT +// solhint-disable no-inline-assembly + +import "../interfaces/PackedUserOperation.sol"; +import "../core/UserOperationLib.sol"; + +library Eip7702Support { + + // EIP-7702 code prefix before delegate address. + bytes3 internal constant EIP7702_PREFIX = 0xef0100; + + // EIP-7702 initCode marker, to specify this account is EIP-7702. + bytes2 internal constant INITCODE_EIP7702_MARKER = 0x7702; + + using UserOperationLib for PackedUserOperation; + + /** + * Get the alternative 'InitCodeHash' value for the UserOp hash calculation when using EIP-7702. + * + * @param userOp - the UserOperation to for the 'InitCodeHash' calculation. + * @return the 'InitCodeHash' value. + */ + function _getEip7702InitCodeHashOverride(PackedUserOperation calldata userOp) internal view returns (bytes32) { + bytes calldata initCode = userOp.initCode; + if (!_isEip7702InitCode(initCode)) { + return 0; + } + address delegate = _getEip7702Delegate(userOp.sender); + if (initCode.length <= 20) + return keccak256(abi.encodePacked(delegate)); + else + return keccak256(abi.encodePacked(delegate, initCode[20 :])); + } + + /** + * Check if this 'initCode' is actually an EIP-7702 authorization. + * This is indicated by 'initCode' that starts with INITCODE_EIP7702_MARKER. + * + * @param initCode - the 'initCode' to check. + * @return true if the 'initCode' is EIP-7702 authorization, false otherwise. + */ + function _isEip7702InitCode(bytes calldata initCode) internal pure returns (bool) { + + if (initCode.length < 2) { + return false; + } + bytes20 initCodeStart; + // non-empty calldata bytes are always zero-padded to 32-bytes, so can be safely casted to "bytes20" + assembly ("memory-safe") { + initCodeStart := calldataload(initCode.offset) + } + // make sure first 20 bytes of initCode are "0x7702" (padded with zeros) + return initCodeStart == bytes20(INITCODE_EIP7702_MARKER); + } + + /** + * Get the EIP-7702 delegate from contract code. + * Must only be used if _isEip7702InitCode(initCode) is true. + * + * @param sender - the EIP-7702 'sender' account to get the delegated contract code address. + * @return the address of the EIP-7702 authorized contract. + */ + function _getEip7702Delegate(address sender) internal view returns (address) { + + bytes32 senderCode; + + assembly ("memory-safe") { + extcodecopy(sender, 0, 0, 23) + senderCode := mload(0) + } + // To be a valid EIP-7702 delegate, the first 3 bytes are EIP7702_PREFIX + // followed by the delegate address + if (bytes3(senderCode) != EIP7702_PREFIX) { + // instead of just "not an EIP-7702 delegate", if some info. + require(sender.code.length > 0, "sender has no code"); + revert("not an EIP-7702 delegate"); + } + return address(bytes20(senderCode << 24)); + } +} diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/EntryPoint.sol b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/EntryPoint.sol new file mode 100644 index 00000000..7c2ddce1 --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/EntryPoint.sol @@ -0,0 +1,958 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.28; +/* solhint-disable avoid-low-level-calls */ +/* solhint-disable no-inline-assembly */ + +import "../interfaces/IAccount.sol"; +import "../interfaces/IAccountExecute.sol"; +import "../interfaces/IEntryPoint.sol"; +import "../interfaces/IPaymaster.sol"; + +import "./UserOperationLib.sol"; +import "./StakeManager.sol"; +import "./NonceManager.sol"; +import "./Helpers.sol"; +import "./SenderCreator.sol"; +import "./Eip7702Support.sol"; +import "../utils/Exec.sol"; + +import "@openzeppelin/contracts/utils/ReentrancyGuardTransient.sol"; +import "@openzeppelin/contracts/utils/introspection/ERC165.sol"; +import "@openzeppelin/contracts/utils/cryptography/EIP712.sol"; + +/** + * Account-Abstraction (EIP-4337) singleton EntryPoint v0.8 implementation. + * Only one instance required on each chain. + * @custom:security-contact https://bounty.ethereum.org + */ +contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuardTransient, ERC165, EIP712 { + + using UserOperationLib for PackedUserOperation; + + /** + * internal-use constants + */ + + // allow some slack for future gas price changes. + uint256 private constant INNER_GAS_OVERHEAD = 10000; + + // Marker for inner call revert on out of gas + bytes32 private constant INNER_OUT_OF_GAS = hex"deaddead"; + bytes32 private constant INNER_REVERT_LOW_PREFUND = hex"deadaa51"; + + uint256 private constant REVERT_REASON_MAX_LEN = 2048; + // Penalty charged for either unused execution gas or postOp gas + uint256 private constant UNUSED_GAS_PENALTY_PERCENT = 10; + // Threshold below which no penalty would be charged + uint256 private constant PENALTY_GAS_THRESHOLD = 40000; + + SenderCreator private immutable _senderCreator = new SenderCreator(); + + string constant internal DOMAIN_NAME = "ERC4337"; + string constant internal DOMAIN_VERSION = "1"; + + constructor() EIP712(DOMAIN_NAME, DOMAIN_VERSION) { + } + + /// @inheritdoc IEntryPoint + function handleOps( + PackedUserOperation[] calldata ops, + address payable beneficiary + ) external nonReentrant { + uint256 opslen = ops.length; + UserOpInfo[] memory opInfos = new UserOpInfo[](opslen); + unchecked { + _iterateValidationPhase(ops, opInfos, address(0), 0); + + uint256 collected = 0; + emit BeforeExecution(); + + for (uint256 i = 0; i < opslen; i++) { + collected += _executeUserOp(i, ops[i], opInfos[i]); + } + + _compensate(beneficiary, collected); + } + } + + /// @inheritdoc IEntryPoint + function handleAggregatedOps( + UserOpsPerAggregator[] calldata opsPerAggregator, + address payable beneficiary + ) external nonReentrant { + + unchecked { + uint256 opasLen = opsPerAggregator.length; + uint256 totalOps = 0; + for (uint256 i = 0; i < opasLen; i++) { + UserOpsPerAggregator calldata opa = opsPerAggregator[i]; + PackedUserOperation[] calldata ops = opa.userOps; + IAggregator aggregator = opa.aggregator; + + // address(1) is special marker of "signature error" + require( + address(aggregator) != address(1), + SignatureValidationFailed(address(aggregator)) + ); + + if (address(aggregator) != address(0)) { + // solhint-disable-next-line no-empty-blocks + try aggregator.validateSignatures(ops, opa.signature) {} catch { + revert SignatureValidationFailed(address(aggregator)); + } + } + + totalOps += ops.length; + } + + UserOpInfo[] memory opInfos = new UserOpInfo[](totalOps); + + uint256 opIndex = 0; + for (uint256 a = 0; a < opasLen; a++) { + UserOpsPerAggregator calldata opa = opsPerAggregator[a]; + PackedUserOperation[] calldata ops = opa.userOps; + IAggregator aggregator = opa.aggregator; + + opIndex += _iterateValidationPhase(ops, opInfos, address(aggregator), opIndex); + } + + emit BeforeExecution(); + + uint256 collected = 0; + opIndex = 0; + for (uint256 a = 0; a < opasLen; a++) { + UserOpsPerAggregator calldata opa = opsPerAggregator[a]; + emit SignatureAggregatorChanged(address(opa.aggregator)); + PackedUserOperation[] calldata ops = opa.userOps; + uint256 opslen = ops.length; + + for (uint256 i = 0; i < opslen; i++) { + collected += _executeUserOp(opIndex, ops[i], opInfos[opIndex]); + opIndex++; + } + } + + _compensate(beneficiary, collected); + } + } + + /// @inheritdoc IEntryPoint + function getUserOpHash( + PackedUserOperation calldata userOp + ) public view returns (bytes32) { + bytes32 overrideInitCodeHash = Eip7702Support._getEip7702InitCodeHashOverride(userOp); + return + MessageHashUtils.toTypedDataHash(getDomainSeparatorV4(), userOp.hash(overrideInitCodeHash)); + } + + /// @inheritdoc IEntryPoint + function getSenderAddress(bytes calldata initCode) external { + address sender = senderCreator().createSender(initCode); + revert SenderAddressResult(sender); + } + + /// @inheritdoc IEntryPoint + function senderCreator() public view virtual returns (ISenderCreator) { + return _senderCreator; + } + + /// @inheritdoc IEntryPoint + function delegateAndRevert(address target, bytes calldata data) external { + (bool success, bytes memory ret) = target.delegatecall(data); + revert DelegateAndRevert(success, ret); + } + + function getPackedUserOpTypeHash() external pure returns (bytes32) { + return UserOperationLib.PACKED_USEROP_TYPEHASH; + } + + function getDomainSeparatorV4() public virtual view returns (bytes32) { + return _domainSeparatorV4(); + } + + /// @inheritdoc IERC165 + function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { + // note: solidity "type(IEntryPoint).interfaceId" is without inherited methods but we want to check everything + return interfaceId == (type(IEntryPoint).interfaceId ^ type(IStakeManager).interfaceId ^ type(INonceManager).interfaceId) || + interfaceId == type(IEntryPoint).interfaceId || + interfaceId == type(IStakeManager).interfaceId || + interfaceId == type(INonceManager).interfaceId || + super.supportsInterface(interfaceId); + } + + /** + * Compensate the caller's beneficiary address with the collected fees of all UserOperations. + * @param beneficiary - The address to receive the fees. + * @param amount - Amount to transfer. + */ + function _compensate(address payable beneficiary, uint256 amount) internal virtual { + require(beneficiary != address(0), "AA90 invalid beneficiary"); + (bool success,) = beneficiary.call{value: amount}(""); + require(success, "AA91 failed send to beneficiary"); + } + + /** + * Execute a user operation. + * @param opIndex - Index into the opInfo array. + * @param userOp - The userOp to execute. + * @param opInfo - The opInfo filled by validatePrepayment for this userOp. + * @return collected - The total amount this userOp paid. + */ + function _executeUserOp( + uint256 opIndex, + PackedUserOperation calldata userOp, + UserOpInfo memory opInfo + ) + internal virtual + returns (uint256 collected) { + uint256 preGas = gasleft(); + bytes memory context = _getMemoryBytesFromOffset(opInfo.contextOffset); + bool success; + { + uint256 saveFreePtr = _getFreePtr(); + bytes calldata callData = userOp.callData; + bytes memory innerCall; + bytes4 methodSig; + assembly ("memory-safe") { + let len := callData.length + if gt(len, 3) { + methodSig := calldataload(callData.offset) + } + } + if (methodSig == IAccountExecute.executeUserOp.selector) { + bytes memory executeUserOp = abi.encodeCall(IAccountExecute.executeUserOp, (userOp, opInfo.userOpHash)); + innerCall = abi.encodeCall(this.innerHandleOp, (executeUserOp, opInfo, context)); + } else + { + innerCall = abi.encodeCall(this.innerHandleOp, (callData, opInfo, context)); + } + assembly ("memory-safe") { + success := call(gas(), address(), 0, add(innerCall, 0x20), mload(innerCall), 0, 32) + collected := mload(0) + } + _restoreFreePtr(saveFreePtr); + } + if (!success) { + bytes32 innerRevertCode; + assembly ("memory-safe") { + let len := returndatasize() + if eq(32, len) { + returndatacopy(0, 0, 32) + innerRevertCode := mload(0) + } + } + if (innerRevertCode == INNER_OUT_OF_GAS) { + // handleOps was called with gas limit too low. abort entire bundle. + // can only be caused by bundler (leaving not enough gas for inner call) + revert FailedOp(opIndex, "AA95 out of gas"); + } else if (innerRevertCode == INNER_REVERT_LOW_PREFUND) { + // innerCall reverted on prefund too low. treat entire prefund as "gas cost" + uint256 actualGas = preGas - gasleft() + opInfo.preOpGas; + uint256 actualGasCost = opInfo.prefund; + _emitPrefundTooLow(opInfo); + _emitUserOperationEvent(opInfo, false, actualGasCost, actualGas); + collected = actualGasCost; + } else { + uint256 freePtr = _getFreePtr(); + emit PostOpRevertReason( + opInfo.userOpHash, + opInfo.mUserOp.sender, + opInfo.mUserOp.nonce, + Exec.getReturnData(REVERT_REASON_MAX_LEN) + ); + _restoreFreePtr(freePtr); + + uint256 actualGas = preGas - gasleft() + opInfo.preOpGas; + collected = _postExecution( + IPaymaster.PostOpMode.postOpReverted, + opInfo, + context, + actualGas + ); + } + } + } + + /** + * Emit the UserOperationEvent for the given UserOperation. + * + * @param opInfo - The details of the current UserOperation. + * @param success - Whether the execution of the UserOperation has succeeded or not. + * @param actualGasCost - The actual cost of the consumed gas charged from the sender or the paymaster. + * @param actualGas - The actual amount of gas used. + */ + function _emitUserOperationEvent(UserOpInfo memory opInfo, bool success, uint256 actualGasCost, uint256 actualGas) internal virtual { + emit UserOperationEvent( + opInfo.userOpHash, + opInfo.mUserOp.sender, + opInfo.mUserOp.paymaster, + opInfo.mUserOp.nonce, + success, + actualGasCost, + actualGas + ); + } + + /** + * Emit the UserOperationPrefundTooLow event for the given UserOperation. + * + * @param opInfo - The details of the current UserOperation. + */ + function _emitPrefundTooLow(UserOpInfo memory opInfo) internal virtual { + emit UserOperationPrefundTooLow( + opInfo.userOpHash, + opInfo.mUserOp.sender, + opInfo.mUserOp.nonce + ); + } + + /** + * Iterate over calldata PackedUserOperation array and perform account and paymaster validation. + * @notice UserOpInfo is a global array of all UserOps while PackedUserOperation is grouped per aggregator. + * + * @param ops - an array of UserOps to be validated + * @param opInfos - an array of UserOp metadata being read and filled in during this function's execution + * @param expectedAggregator - an address of the aggregator specified for a given UserOp if any, or address(0) + * @param opIndexOffset - an offset for the index between 'ops' and 'opInfos' arrays, see the notice. + * @return opsLen - processed UserOps (length of "ops" array) + */ + function _iterateValidationPhase( + PackedUserOperation[] calldata ops, + UserOpInfo[] memory opInfos, + address expectedAggregator, + uint256 opIndexOffset + ) internal returns (uint256 opsLen){ + unchecked { + opsLen = ops.length; + for (uint256 i = 0; i < opsLen; i++) { + UserOpInfo memory opInfo = opInfos[opIndexOffset + i]; + ( + uint256 validationData, + uint256 pmValidationData + ) = _validatePrepayment(opIndexOffset + i, ops[i], opInfo); + _validateAccountAndPaymasterValidationData( + opIndexOffset + i, + validationData, + pmValidationData, + expectedAggregator + ); + } + } + } + + /** + * A memory copy of UserOp static fields only. + * Excluding: callData, initCode and signature. Replacing paymasterAndData with paymaster. + */ + struct MemoryUserOp { + address sender; + uint256 nonce; + uint256 verificationGasLimit; + uint256 callGasLimit; + uint256 paymasterVerificationGasLimit; + uint256 paymasterPostOpGasLimit; + uint256 preVerificationGas; + address paymaster; + uint256 maxFeePerGas; + uint256 maxPriorityFeePerGas; + } + + struct UserOpInfo { + MemoryUserOp mUserOp; + bytes32 userOpHash; + uint256 prefund; + uint256 contextOffset; + uint256 preOpGas; + } + + /** + * Inner function to handle a UserOperation. + * Must be declared "external" to open a call context, but it can only be called by handleOps. + * @param callData - The callData to execute. + * @param opInfo - The UserOpInfo struct. + * @param context - The context bytes. + * @return actualGasCost - the actual cost in eth this UserOperation paid for gas + */ + function innerHandleOp( + bytes memory callData, + UserOpInfo memory opInfo, + bytes calldata context + ) external returns (uint256 actualGasCost) { + uint256 preGas = gasleft(); + require(msg.sender == address(this), "AA92 internal call only"); + MemoryUserOp memory mUserOp = opInfo.mUserOp; + + uint256 callGasLimit = mUserOp.callGasLimit; + unchecked { + // handleOps was called with gas limit too low. abort entire bundle. + if ( + gasleft() * 63 / 64 < + callGasLimit + + mUserOp.paymasterPostOpGasLimit + + INNER_GAS_OVERHEAD + ) { + assembly ("memory-safe") { + mstore(0, INNER_OUT_OF_GAS) + revert(0, 32) + } + } + } + + IPaymaster.PostOpMode mode = IPaymaster.PostOpMode.opSucceeded; + if (callData.length > 0) { + bool success = Exec.call(mUserOp.sender, 0, callData, callGasLimit); + if (!success) { + uint256 freePtr = _getFreePtr(); + bytes memory result = Exec.getReturnData(REVERT_REASON_MAX_LEN); + if (result.length > 0) { + emit UserOperationRevertReason( + opInfo.userOpHash, + mUserOp.sender, + mUserOp.nonce, + result + ); + } + _restoreFreePtr(freePtr); + mode = IPaymaster.PostOpMode.opReverted; + } + } + + unchecked { + uint256 actualGas = preGas - gasleft() + opInfo.preOpGas; + return _postExecution(mode, opInfo, context, actualGas); + } + } + + /** + * Copy general fields from userOp into the memory opInfo structure. + * @param userOp - The user operation. + * @param mUserOp - The memory user operation. + */ + function _copyUserOpToMemory( + PackedUserOperation calldata userOp, + MemoryUserOp memory mUserOp + ) internal virtual pure { + mUserOp.sender = userOp.sender; + mUserOp.nonce = userOp.nonce; + (mUserOp.verificationGasLimit, mUserOp.callGasLimit) = UserOperationLib.unpackUints(userOp.accountGasLimits); + mUserOp.preVerificationGas = userOp.preVerificationGas; + (mUserOp.maxPriorityFeePerGas, mUserOp.maxFeePerGas) = UserOperationLib.unpackUints(userOp.gasFees); + bytes calldata paymasterAndData = userOp.paymasterAndData; + if (paymasterAndData.length > 0) { + require( + paymasterAndData.length >= UserOperationLib.PAYMASTER_DATA_OFFSET, + "AA93 invalid paymasterAndData" + ); + address paymaster; + (paymaster, mUserOp.paymasterVerificationGasLimit, mUserOp.paymasterPostOpGasLimit) = UserOperationLib.unpackPaymasterStaticFields(paymasterAndData); + require(paymaster != address(0), "AA98 invalid paymaster"); + mUserOp.paymaster = paymaster; + } + } + + /** + * Get the required prefunded gas fee amount for an operation. + * + * @param mUserOp - The user operation in memory. + * @return requiredPrefund - the required amount. + */ + function _getRequiredPrefund( + MemoryUserOp memory mUserOp + ) internal virtual pure returns (uint256 requiredPrefund) { + unchecked { + uint256 requiredGas = mUserOp.verificationGasLimit + + mUserOp.callGasLimit + + mUserOp.paymasterVerificationGasLimit + + mUserOp.paymasterPostOpGasLimit + + mUserOp.preVerificationGas; + + requiredPrefund = requiredGas * mUserOp.maxFeePerGas; + } + } + + /** + * Create sender smart contract account if init code is provided. + * @param opIndex - The operation index. + * @param opInfo - The operation info. + * @param initCode - The init code for the smart contract account. + */ + function _createSenderIfNeeded( + uint256 opIndex, + UserOpInfo memory opInfo, + bytes calldata initCode + ) internal virtual { + if (initCode.length != 0) { + address sender = opInfo.mUserOp.sender; + if (Eip7702Support._isEip7702InitCode(initCode)) { + if (initCode.length > 20) { + // Already validated it is an EIP-7702 delegate (and hence, already has code) - see getUserOpHash() + // Note: Can be called multiple times as long as an appropriate initCode is supplied + senderCreator().initEip7702Sender{ + gas: opInfo.mUserOp.verificationGasLimit + }(sender, initCode[20 :]); + } + return; + } + if (sender.code.length != 0) + revert FailedOp(opIndex, "AA10 sender already constructed"); + if (initCode.length < 20) { + revert FailedOp(opIndex, "AA99 initCode too small"); + } + address sender1 = senderCreator().createSender{ + gas: opInfo.mUserOp.verificationGasLimit + }(initCode); + if (sender1 == address(0)) + revert FailedOp(opIndex, "AA13 initCode failed or OOG"); + if (sender1 != sender) + revert FailedOp(opIndex, "AA14 initCode must return sender"); + if (sender1.code.length == 0) + revert FailedOp(opIndex, "AA15 initCode must create sender"); + address factory = address(bytes20(initCode[0 : 20])); + emit AccountDeployed( + opInfo.userOpHash, + sender, + factory, + opInfo.mUserOp.paymaster + ); + } + } + + /** + * Call account.validateUserOp. + * Revert (with FailedOp) in case validateUserOp reverts, or account didn't send required prefund. + * Decrement account's deposit if needed. + * @param opIndex - The operation index. + * @param op - The user operation. + * @param opInfo - The operation info. + * @param requiredPrefund - The required prefund amount. + * @return validationData - The account's validationData. + */ + function _validateAccountPrepayment( + uint256 opIndex, + PackedUserOperation calldata op, + UserOpInfo memory opInfo, + uint256 requiredPrefund + ) + internal virtual + returns ( + uint256 validationData + ) + { + unchecked { + MemoryUserOp memory mUserOp = opInfo.mUserOp; + address sender = mUserOp.sender; + _createSenderIfNeeded(opIndex, opInfo, op.initCode); + address paymaster = mUserOp.paymaster; + uint256 missingAccountFunds = 0; + if (paymaster == address(0)) { + uint256 bal = balanceOf(sender); + missingAccountFunds = bal > requiredPrefund + ? 0 + : requiredPrefund - bal; + } + validationData = _callValidateUserOp(opIndex, op, opInfo, missingAccountFunds); + if (paymaster == address(0)) { + if (!_tryDecrementDeposit(sender, requiredPrefund)) { + revert FailedOp(opIndex, "AA21 didn't pay prefund"); + } + } + } + } + + /** + * Make a call to the sender.validateUserOp() function. + * Handle wrong output size by reverting with a FailedOp error. + * + * @param opIndex - index of the UserOperation in the bundle. + * @param op - the packed UserOperation object. + * @param opInfo - the in-memory UserOperation information. + * @param missingAccountFunds - the amount of deposit the account has to make to cover the UserOperation gas. + */ + function _callValidateUserOp( + uint256 opIndex, + PackedUserOperation calldata op, + UserOpInfo memory opInfo, + uint256 missingAccountFunds + ) + internal virtual returns (uint256 validationData) { + uint256 gasLimit = opInfo.mUserOp.verificationGasLimit; + address sender = opInfo.mUserOp.sender; + bool success; + { + uint256 saveFreePtr = _getFreePtr(); + bytes memory callData = abi.encodeCall(IAccount.validateUserOp, (op, opInfo.userOpHash, missingAccountFunds)); + assembly ("memory-safe"){ + success := call(gasLimit, sender, 0, add(callData, 0x20), mload(callData), 0, 32) + validationData := mload(0) + // any return data size other than 32 is considered failure + if iszero(eq(returndatasize(), 32)) { + success := 0 + } + } + _restoreFreePtr(saveFreePtr); + } + if (!success) { + if (sender.code.length == 0) { + revert FailedOp(opIndex, "AA20 account not deployed"); + } else { + revert FailedOpWithRevert(opIndex, "AA23 reverted", Exec.getReturnData(REVERT_REASON_MAX_LEN)); + } + } + } + + /** + * In case the request has a paymaster: + * - Validate paymaster has enough deposit. + * - Call paymaster.validatePaymasterUserOp. + * - Revert with proper FailedOp in case paymaster reverts. + * - Decrement paymaster's deposit. + * @param opIndex - The operation index. + * @param op - The user operation. + * @param opInfo - The operation info. + * @return context - The Paymaster-provided value to be passed to the 'postOp' function later + * @return validationData - The Paymaster's validationData. + */ + function _validatePaymasterPrepayment( + uint256 opIndex, + PackedUserOperation calldata op, + UserOpInfo memory opInfo + ) internal virtual returns (bytes memory context, uint256 validationData) { + unchecked { + uint256 preGas = gasleft(); + MemoryUserOp memory mUserOp = opInfo.mUserOp; + address paymaster = mUserOp.paymaster; + uint256 requiredPreFund = opInfo.prefund; + if (!_tryDecrementDeposit(paymaster, requiredPreFund)) { + revert FailedOp(opIndex, "AA31 paymaster deposit too low"); + } + uint256 pmVerificationGasLimit = mUserOp.paymasterVerificationGasLimit; + (context, validationData) = _callValidatePaymasterUserOp(opIndex, op, opInfo); + if (preGas - gasleft() > pmVerificationGasLimit) { + revert FailedOp(opIndex, "AA36 over paymasterVerificationGasLimit"); + } + } + } + + function _callValidatePaymasterUserOp( + uint256 opIndex, + PackedUserOperation calldata op, + UserOpInfo memory opInfo + ) internal returns (bytes memory context, uint256 validationData) { + uint256 freePtr = _getFreePtr(); + bytes memory validatePaymasterCall = abi.encodeCall( + IPaymaster.validatePaymasterUserOp, + (op, opInfo.userOpHash, opInfo.prefund) + ); + address paymaster = opInfo.mUserOp.paymaster; + uint256 paymasterVerificationGasLimit = opInfo.mUserOp.paymasterVerificationGasLimit; + bool success; + uint256 contextLength; + uint256 contextOffset; + uint256 maxContextLength; + uint256 len; + assembly ("memory-safe") { + success := call(paymasterVerificationGasLimit, paymaster, 0, add(validatePaymasterCall, 0x20), mload(validatePaymasterCall), 0, 0) + len := returndatasize() + // return data from validatePaymasterUserOp is (bytes context, validationData) + // encoded as: + // 32 bytes offset of context (always 64) + // 32 bytes of validationData + // 32 bytes of context length + // context data (rounded up, to 32 bytes boundary) + // so entire buffer size is (at least) 96+content.length. + // + // we use freePtr, fetched before calling encodeCall, as return data pointer. + // this way we reuse that memory without unnecessary memory expansion + returndatacopy(freePtr, 0, len) + validationData := mload(add(freePtr, 32)) + contextOffset := mload(freePtr) + maxContextLength := sub(len, 96) + context := add(freePtr, 64) + contextLength := mload(context) + } + + unchecked { + if (!success || contextOffset != 64 || contextLength + 31 < maxContextLength) { + revert FailedOpWithRevert(opIndex, "AA33 reverted", Exec.getReturnData(REVERT_REASON_MAX_LEN)); + } + } + finalizeAllocation(freePtr, len); + } + + /** + * Revert if either account validationData or paymaster validationData is expired. + * @param opIndex - The operation index. + * @param validationData - The account validationData. + * @param paymasterValidationData - The paymaster validationData. + * @param expectedAggregator - The expected aggregator. + */ + function _validateAccountAndPaymasterValidationData( + uint256 opIndex, + uint256 validationData, + uint256 paymasterValidationData, + address expectedAggregator + ) internal virtual view { + (address aggregator, bool outOfTimeRange) = _getValidationData( + validationData + ); + if (expectedAggregator != aggregator) { + revert FailedOp(opIndex, "AA24 signature error"); + } + if (outOfTimeRange) { + revert FailedOp(opIndex, "AA22 expired or not due"); + } + // pmAggregator is not a real signature aggregator: we don't have logic to handle it as address. + // Non-zero address means that the paymaster fails due to some signature check (which is ok only during estimation). + address pmAggregator; + (pmAggregator, outOfTimeRange) = _getValidationData( + paymasterValidationData + ); + if (pmAggregator != address(0)) { + revert FailedOp(opIndex, "AA34 signature error"); + } + if (outOfTimeRange) { + revert FailedOp(opIndex, "AA32 paymaster expired or not due"); + } + } + + /** + * Parse validationData into its components. + * @param validationData - The packed validation data (sigFailed, validAfter, validUntil). + * @return aggregator the aggregator of the validationData + * @return outOfTimeRange true if current time is outside the time range of this validationData. + */ + function _getValidationData( + uint256 validationData + ) internal virtual view returns (address aggregator, bool outOfTimeRange) { + if (validationData == 0) { + return (address(0), false); + } + ValidationData memory data = _parseValidationData(validationData); + // solhint-disable-next-line not-rely-on-time + outOfTimeRange = block.timestamp > data.validUntil || block.timestamp <= data.validAfter; + aggregator = data.aggregator; + } + + /** + * Validate account and paymaster (if defined) and + * also make sure total validation doesn't exceed verificationGasLimit. + * This method is called off-chain (simulateValidation()) and on-chain (from handleOps) + * @param opIndex - The index of this userOp into the "opInfos" array. + * @param userOp - The packed calldata UserOperation structure to validate. + * @param outOpInfo - The empty unpacked in-memory UserOperation structure that will be filled in here. + * + * @return validationData - The account's validationData. + * @return paymasterValidationData - The paymaster's validationData. + */ + function _validatePrepayment( + uint256 opIndex, + PackedUserOperation calldata userOp, + UserOpInfo memory outOpInfo + ) + internal virtual + returns (uint256 validationData, uint256 paymasterValidationData) + { + uint256 preGas = gasleft(); + MemoryUserOp memory mUserOp = outOpInfo.mUserOp; + _copyUserOpToMemory(userOp, mUserOp); + + // getUserOpHash uses temporary allocations, no required after it returns + uint256 freePtr = _getFreePtr(); + outOpInfo.userOpHash = getUserOpHash(userOp); + _restoreFreePtr(freePtr); + + // Validate all numeric values in userOp are well below 128 bit, so they can safely be added + // and multiplied without causing overflow. + uint256 verificationGasLimit = mUserOp.verificationGasLimit; + uint256 maxGasValues = mUserOp.preVerificationGas | + verificationGasLimit | + mUserOp.callGasLimit | + mUserOp.paymasterVerificationGasLimit | + mUserOp.paymasterPostOpGasLimit | + mUserOp.maxFeePerGas | + mUserOp.maxPriorityFeePerGas; + require(maxGasValues <= type(uint120).max, FailedOp(opIndex, "AA94 gas values overflow")); + + uint256 requiredPreFund = _getRequiredPrefund(mUserOp); + outOpInfo.prefund = requiredPreFund; + validationData = _validateAccountPrepayment( + opIndex, + userOp, + outOpInfo, + requiredPreFund + ); + + require( + _validateAndUpdateNonce(mUserOp.sender, mUserOp.nonce), + FailedOp(opIndex, "AA25 invalid account nonce") + ); + + unchecked { + if (preGas - gasleft() > verificationGasLimit) { + revert FailedOp(opIndex, "AA26 over verificationGasLimit"); + } + } + + bytes memory context; + if (mUserOp.paymaster != address(0)) { + (context, paymasterValidationData) = _validatePaymasterPrepayment( + opIndex, + userOp, + outOpInfo + ); + } + unchecked { + outOpInfo.contextOffset = _getOffsetOfMemoryBytes(context); + outOpInfo.preOpGas = preGas - gasleft() + userOp.preVerificationGas; + } + } + + /** + * Process post-operation, called just after the callData is executed. + * If a paymaster is defined and its validation returned a non-empty context, its postOp is called. + * The excess amount is refunded to the account (or paymaster - if it was used in the request). + * @param mode - Whether is called from innerHandleOp, or outside (postOpReverted). + * @param opInfo - UserOp fields and info collected during validation. + * @param context - The context returned in validatePaymasterUserOp. + * @param actualGas - The gas used so far by this user operation. + * + * @return actualGasCost - the actual cost in eth this UserOperation paid for gas + */ + function _postExecution( + IPaymaster.PostOpMode mode, + UserOpInfo memory opInfo, + bytes memory context, + uint256 actualGas + ) internal virtual returns (uint256 actualGasCost) { + uint256 preGas = gasleft(); + unchecked { + address refundAddress; + MemoryUserOp memory mUserOp = opInfo.mUserOp; + uint256 gasPrice = _getUserOpGasPrice(mUserOp); + + address paymaster = mUserOp.paymaster; + // Calculating a penalty for unused execution gas + { + uint256 executionGasUsed = actualGas - opInfo.preOpGas; + // this check is required for the gas used within EntryPoint and not covered by explicit gas limits + actualGas += _getUnusedGasPenalty(executionGasUsed, mUserOp.callGasLimit); + } + uint256 postOpUnusedGasPenalty; + if (paymaster == address(0)) { + refundAddress = mUserOp.sender; + } else { + refundAddress = paymaster; + if (context.length > 0) { + actualGasCost = actualGas * gasPrice; + uint256 postOpPreGas = gasleft(); + if (mode != IPaymaster.PostOpMode.postOpReverted) { + try IPaymaster(paymaster).postOp{ + gas: mUserOp.paymasterPostOpGasLimit + }(mode, context, actualGasCost, gasPrice) + // solhint-disable-next-line no-empty-blocks + {} catch { + bytes memory reason = Exec.getReturnData(REVERT_REASON_MAX_LEN); + revert PostOpReverted(reason); + } + } + // Calculating a penalty for unused postOp gas + // note that if postOp is reverted, the maximum penalty (10% of postOpGasLimit) is charged. + uint256 postOpGasUsed = postOpPreGas - gasleft(); + postOpUnusedGasPenalty = _getUnusedGasPenalty(postOpGasUsed, mUserOp.paymasterPostOpGasLimit); + } + } + actualGas += preGas - gasleft() + postOpUnusedGasPenalty; + actualGasCost = actualGas * gasPrice; + uint256 prefund = opInfo.prefund; + if (prefund < actualGasCost) { + if (mode == IPaymaster.PostOpMode.postOpReverted) { + actualGasCost = prefund; + _emitPrefundTooLow(opInfo); + _emitUserOperationEvent(opInfo, false, actualGasCost, actualGas); + } else { + assembly ("memory-safe") { + mstore(0, INNER_REVERT_LOW_PREFUND) + revert(0, 32) + } + } + } else { + uint256 refund = prefund - actualGasCost; + _incrementDeposit(refundAddress, refund); + bool success = mode == IPaymaster.PostOpMode.opSucceeded; + _emitUserOperationEvent(opInfo, success, actualGasCost, actualGas); + } + } // unchecked + } + + /** + * The gas price this UserOp agrees to pay. + * Relayer/block builder might submit the TX with higher priorityFee, but the user should not be affected. + * @param mUserOp - The userOp to get the gas price from. + */ + function _getUserOpGasPrice( + MemoryUserOp memory mUserOp + ) internal view returns (uint256) { + unchecked { + uint256 maxFeePerGas = mUserOp.maxFeePerGas; + uint256 maxPriorityFeePerGas = mUserOp.maxPriorityFeePerGas; + return min(maxFeePerGas, maxPriorityFeePerGas + block.basefee); + } + } + + /** + * The offset of the given bytes in memory. + * @param data - The bytes to get the offset of. + */ + function _getOffsetOfMemoryBytes( + bytes memory data + ) internal pure returns (uint256 offset) { + assembly ("memory-safe") { + offset := data + } + } + + /** + * The bytes in memory at the given offset. + * @param offset - The offset to get the bytes from. + */ + function _getMemoryBytesFromOffset( + uint256 offset + ) internal pure returns (bytes memory data) { + assembly ("memory-safe") { + data := offset + } + } + + /** + * save free memory pointer. + * save "free memory" pointer, so that it can be restored later using restoreFreePtr. + * This reduce unneeded memory expansion, and reduce memory expansion cost. + * NOTE: all dynamic allocations between saveFreePtr and restoreFreePtr MUST NOT be used after restoreFreePtr is called. + */ + function _getFreePtr() internal pure returns (uint256 ptr) { + assembly ("memory-safe") { + ptr := mload(0x40) + } + } + + /** + * restore free memory pointer. + * any allocated memory since saveFreePtr is cleared, and MUST NOT be accessed later. + */ + function _restoreFreePtr(uint256 ptr) internal pure { + assembly ("memory-safe") { + mstore(0x40, ptr) + } + } + + function _getUnusedGasPenalty(uint256 gasUsed, uint256 gasLimit) internal pure returns (uint256) { + unchecked { + if (gasLimit <= gasUsed + PENALTY_GAS_THRESHOLD) { + return 0; + } + uint256 unusedGas = gasLimit - gasUsed; + uint256 unusedGasPenalty = (unusedGas * UNUSED_GAS_PENALTY_PERCENT) / 100; + return unusedGasPenalty; + } + } +} diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/EntryPointSimulations.sol b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/EntryPointSimulations.sol new file mode 100644 index 00000000..76e31d3c --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/EntryPointSimulations.sol @@ -0,0 +1,215 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.28; + +/* solhint-disable avoid-low-level-calls */ +/* solhint-disable no-inline-assembly */ + +import "./EntryPoint.sol"; +import "../interfaces/IEntryPointSimulations.sol"; + +/* + * This contract inherits the EntryPoint and extends it with the view-only methods that are executed by + * the bundler in order to check UserOperation validity and estimate its gas consumption. + * This contract should never be deployed on-chain and is only used as a parameter for the "eth_call" request. + */ +contract EntryPointSimulations is EntryPoint, IEntryPointSimulations { + + SenderCreator private _senderCreator; + + bytes32 private __domainSeparatorV4; + + function initSenderCreator() internal virtual { + // This is the address of the first contract created with CREATE by this address. + address createdObj = address(uint160(uint256(keccak256(abi.encodePacked(hex"d694", address(this), hex"01"))))); + _senderCreator = SenderCreator(createdObj); + + _initDomainSeparator(); + } + + function senderCreator() public view virtual override(EntryPoint, IEntryPoint) returns (ISenderCreator) { + // return the same senderCreator as real EntryPoint. + // this call is slightly (100) more expensive than EntryPoint's access to immutable member + return _senderCreator; + } + + /** + * simulation contract should not be deployed, and specifically, accounts should not trust + * it as entrypoint, since the simulation functions don't check the signatures + */ + constructor() { + require(block.number < 1000, "should not be deployed"); + } + + /// @inheritdoc IEntryPointSimulations + function simulateValidation( + PackedUserOperation calldata userOp + ) + external + returns ( + ValidationResult memory + ){ + UserOpInfo memory outOpInfo; + + _simulationOnlyValidations(userOp); + ( + uint256 validationData, + uint256 paymasterValidationData + ) = _validatePrepayment(0, userOp, outOpInfo); + StakeInfo memory paymasterInfo = _getStakeInfo( + outOpInfo.mUserOp.paymaster + ); + StakeInfo memory senderInfo = _getStakeInfo(outOpInfo.mUserOp.sender); + StakeInfo memory factoryInfo; + { + bytes calldata initCode = userOp.initCode; + address factory = initCode.length >= 20 + ? address(bytes20(initCode[0 : 20])) + : address(0); + factoryInfo = _getStakeInfo(factory); + } + + address aggregator = address(uint160(validationData)); + ReturnInfo memory returnInfo = ReturnInfo( + outOpInfo.preOpGas, + outOpInfo.prefund, + validationData, + paymasterValidationData, + _getMemoryBytesFromOffset(outOpInfo.contextOffset) + ); + + AggregatorStakeInfo memory aggregatorInfo; // = NOT_AGGREGATED; + if (uint160(aggregator) != SIG_VALIDATION_SUCCESS && uint160(aggregator) != SIG_VALIDATION_FAILED) { + aggregatorInfo = AggregatorStakeInfo( + aggregator, + _getStakeInfo(aggregator) + ); + } + return ValidationResult( + returnInfo, + senderInfo, + factoryInfo, + paymasterInfo, + aggregatorInfo + ); + } + + /// @inheritdoc IEntryPointSimulations + function simulateHandleOp( + PackedUserOperation calldata op, + address target, + bytes calldata targetCallData + ) + external nonReentrant + returns ( + ExecutionResult memory + ){ + UserOpInfo memory opInfo; + _simulationOnlyValidations(op); + ( + uint256 validationData, + uint256 paymasterValidationData + ) = _validatePrepayment(0, op, opInfo); + + uint256 paid = _executeUserOp(0, op, opInfo); + bool targetSuccess; + bytes memory targetResult; + if (target != address(0)) { + (targetSuccess, targetResult) = target.call(targetCallData); + } + return ExecutionResult( + opInfo.preOpGas, + paid, + validationData, + paymasterValidationData, + targetSuccess, + targetResult + ); + } + + function _simulationOnlyValidations( + PackedUserOperation calldata userOp + ) + internal + { + // Initialize senderCreator(). we can't rely on constructor + initSenderCreator(); + + try + this.validateSenderAndPaymaster( + userOp.initCode, + userOp.sender, + userOp.paymasterAndData + ) + // solhint-disable-next-line no-empty-blocks + {} catch Error(string memory revertReason) { + if (bytes(revertReason).length != 0) { + revert FailedOp(0, revertReason); + } + } + } + + /** + * Called only during simulation by the EntryPointSimulation contract itself and is not meant to be called by external contracts. + * This function always reverts to prevent warm/cold storage differentiation in simulation vs execution. + * @param initCode - The smart account constructor code. + * @param sender - The sender address. + * @param paymasterAndData - The paymaster address (followed by other params, ignored by this method) + */ + function validateSenderAndPaymaster( + bytes calldata initCode, + address sender, + bytes calldata paymasterAndData + ) external view { + if (initCode.length == 0 && sender.code.length == 0) { + // it would revert anyway. but give a meaningful message + revert("AA20 account not deployed"); + } + if (paymasterAndData.length >= 20) { + address paymaster = address(bytes20(paymasterAndData[0 : 20])); + if (paymaster.code.length == 0) { + // It would revert anyway. but give a meaningful message. + revert("AA30 paymaster not deployed"); + } + } + // always revert + revert(""); + } + + // Make sure depositTo cost is more than normal EntryPoint's cost, + // to mitigate DoS vector on the bundler + // empiric test showed that without this wrapper, simulation depositTo costs less.. + function depositTo(address account) public override(IStakeManager, StakeManager) payable { + unchecked{ + // silly code, to waste some gas to make sure depositTo is always little more + // expensive than on-chain call + uint256 x = 1; + while (x < 5) { + x++; + } + StakeManager.depositTo(account); + } + } + + // Copied from EIP712.sol + bytes32 private constant TYPE_HASH = + keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"); + + function __buildDomainSeparator() private view returns (bytes32) { + bytes32 _hashedName = keccak256(bytes(DOMAIN_NAME)); + bytes32 _hashedVersion = keccak256(bytes(DOMAIN_VERSION)); + return keccak256(abi.encode(TYPE_HASH, _hashedName, _hashedVersion, block.chainid, address(this))); + } + + // Can't rely on "immutable" (constructor-initialized) variables" in simulation + function _initDomainSeparator() internal { + __domainSeparatorV4 = __buildDomainSeparator(); + } + + function getDomainSeparatorV4() public override view returns (bytes32) { + return __domainSeparatorV4; + } + + function supportsInterface(bytes4) public view virtual override returns (bool) { + return false; + } +} diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/Helpers.sol b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/Helpers.sol new file mode 100644 index 00000000..25f9fd3e --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/Helpers.sol @@ -0,0 +1,135 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.28; + +/* solhint-disable no-inline-assembly */ + + + /* + * For simulation purposes, validateUserOp (and validatePaymasterUserOp) + * must return this value in case of signature failure, instead of revert. + */ +uint256 constant SIG_VALIDATION_FAILED = 1; + + +/* + * For simulation purposes, validateUserOp (and validatePaymasterUserOp) + * return this value on success. + */ +uint256 constant SIG_VALIDATION_SUCCESS = 0; + + +/** + * Returned data from validateUserOp. + * validateUserOp returns a uint256, which is created by `_packedValidationData` and + * parsed by `_parseValidationData`. + * @param aggregator - address(0) - The account validated the signature by itself. + * address(1) - The account failed to validate the signature. + * otherwise - This is an address of a signature aggregator that must + * be used to validate the signature. + * @param validAfter - This UserOp is valid only after this timestamp. + * @param validUntil - Last timestamp this operation is valid at, or 0 for "indefinitely". + */ +struct ValidationData { + address aggregator; + uint48 validAfter; + uint48 validUntil; +} + +/** + * Extract aggregator/sigFailed, validAfter, validUntil. + * Also convert zero validUntil to type(uint48).max. + * @param validationData - The packed validation data. + * @return data - The unpacked in-memory validation data. + */ +function _parseValidationData( + uint256 validationData +) pure returns (ValidationData memory data) { + address aggregator = address(uint160(validationData)); + uint48 validUntil = uint48(validationData >> 160); + if (validUntil == 0) { + validUntil = type(uint48).max; + } + uint48 validAfter = uint48(validationData >> (48 + 160)); + return ValidationData(aggregator, validAfter, validUntil); +} + +/** + * Helper to pack the return value for validateUserOp. + * @param data - The ValidationData to pack. + * @return the packed validation data. + */ +function _packValidationData( + ValidationData memory data +) pure returns (uint256) { + return + uint160(data.aggregator) | + (uint256(data.validUntil) << 160) | + (uint256(data.validAfter) << (160 + 48)); +} + +/** + * Helper to pack the return value for validateUserOp, when not using an aggregator. + * @param sigFailed - True for signature failure, false for success. + * @param validUntil - Last timestamp this operation is valid at, or 0 for "indefinitely". + * @param validAfter - First timestamp this UserOperation is valid. + * @return the packed validation data. + */ +function _packValidationData( + bool sigFailed, + uint48 validUntil, + uint48 validAfter +) pure returns (uint256) { + return + (sigFailed ? SIG_VALIDATION_FAILED : SIG_VALIDATION_SUCCESS) | + (uint256(validUntil) << 160) | + (uint256(validAfter) << (160 + 48)); +} + +/** + * keccak function over calldata. + * @dev copy calldata into memory, do keccak and drop allocated memory. Strangely, this is more efficient than letting solidity do it. + * + * @param data - the calldata bytes array to perform keccak on. + * @return ret - the keccak hash of the 'data' array. + */ + function calldataKeccak(bytes calldata data) pure returns (bytes32 ret) { + assembly ("memory-safe") { + let mem := mload(0x40) + let len := data.length + calldatacopy(mem, data.offset, len) + ret := keccak256(mem, len) + } + } + + +/** + * The minimum of two numbers. + * @param a - First number. + * @param b - Second number. + * @return - the minimum value. + */ + function min(uint256 a, uint256 b) pure returns (uint256) { + return a < b ? a : b; + } + +/** + * standard solidity memory allocation finalization. + * copied from solidity generated code + * @param memPointer - The current memory pointer + * @param allocationSize - Bytes allocated from memPointer. + */ + function finalizeAllocation(uint256 memPointer, uint256 allocationSize) pure { + + assembly ("memory-safe"){ + finalize_allocation(memPointer, allocationSize) + + function finalize_allocation(memPtr, size) { + let newFreePtr := add(memPtr, round_up_to_mul_of_32(size)) + mstore(64, newFreePtr) + } + + function round_up_to_mul_of_32(value) -> result { + result := and(add(value, 31), not(31)) + } + } + } diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/NonceManager.sol b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/NonceManager.sol new file mode 100644 index 00000000..461c795e --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/NonceManager.sol @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.28; + +import "../interfaces/INonceManager.sol"; + +/** + * nonce management functionality + */ +abstract contract NonceManager is INonceManager { + + /** + * The next valid sequence number for a given nonce key. + */ + mapping(address => mapping(uint192 => uint256)) public nonceSequenceNumber; + + /// @inheritdoc INonceManager + function getNonce(address sender, uint192 key) + public view override returns (uint256 nonce) { + return nonceSequenceNumber[sender][key] | (uint256(key) << 64); + } + + /// @inheritdoc INonceManager + function incrementNonce(uint192 key) external override { + nonceSequenceNumber[msg.sender][key]++; + } + + /** + * validate nonce uniqueness for this account. + * called just after validateUserOp() + * @return true if the nonce was incremented successfully. + * false if the current nonce doesn't match the given one. + */ + function _validateAndUpdateNonce(address sender, uint256 nonce) internal returns (bool) { + + uint192 key = uint192(nonce >> 64); + uint64 seq = uint64(nonce); + return nonceSequenceNumber[sender][key]++ == seq; + } + +} diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/SenderCreator.sol b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/SenderCreator.sol new file mode 100644 index 00000000..4268f792 --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/SenderCreator.sol @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.28; +/* solhint-disable avoid-low-level-calls */ +/* solhint-disable no-inline-assembly */ + +import "../interfaces/ISenderCreator.sol"; +import "../interfaces/IEntryPoint.sol"; +import "../utils/Exec.sol"; + +/** + * Helper contract for EntryPoint, to call userOp.initCode from a "neutral" address, + * which is explicitly not the entryPoint itself. + */ +contract SenderCreator is ISenderCreator { + address public immutable entryPoint; + + constructor(){ + entryPoint = msg.sender; + } + + uint256 private constant REVERT_REASON_MAX_LEN = 2048; + + /** + * Call the "initCode" factory to create and return the sender account address. + * @param initCode - The initCode value from a UserOp. contains 20 bytes of factory address, + * followed by calldata. + * @return sender - The returned address of the created account, or zero address on failure. + */ + function createSender( + bytes calldata initCode + ) external returns (address sender) { + require(msg.sender == entryPoint, "AA97 should call from EntryPoint"); + address factory = address(bytes20(initCode[0 : 20])); + + bytes memory initCallData = initCode[20 :]; + bool success; + assembly ("memory-safe") { + success := call( + gas(), + factory, + 0, + add(initCallData, 0x20), + mload(initCallData), + 0, + 32 + ) + if success { + sender := mload(0) + } + } + } + + /// @inheritdoc ISenderCreator + function initEip7702Sender( + address sender, + bytes memory initCallData + ) external { + require(msg.sender == entryPoint, "AA97 should call from EntryPoint"); + bool success; + assembly ("memory-safe") { + success := call( + gas(), + sender, + 0, + add(initCallData, 0x20), + mload(initCallData), + 0, + 0 + ) + } + if (!success) { + bytes memory result = Exec.getReturnData(REVERT_REASON_MAX_LEN); + revert IEntryPoint.FailedOpWithRevert(0, "AA13 EIP7702 sender init failed", result); + } + } +} diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/StakeManager.sol b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/StakeManager.sol new file mode 100644 index 00000000..f5f8063c --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/StakeManager.sol @@ -0,0 +1,149 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.28; + +import "../interfaces/IStakeManager.sol"; + +/* solhint-disable avoid-low-level-calls */ +/* solhint-disable not-rely-on-time */ + +/** + * Manage deposits and stakes. + * Deposit is just a balance used to pay for UserOperations (either by a paymaster or an account). + * Stake is value locked for at least "unstakeDelay" by a paymaster. + */ +abstract contract StakeManager is IStakeManager { + /// maps paymaster to their deposits and stakes + mapping(address => DepositInfo) private deposits; + + /// @inheritdoc IStakeManager + function getDepositInfo( + address account + ) external view returns (DepositInfo memory info) { + return deposits[account]; + } + + /** + * Internal method to return just the stake info. + * @param addr - The account to query. + */ + function _getStakeInfo( + address addr + ) internal view returns (StakeInfo memory info) { + DepositInfo storage depositInfo = deposits[addr]; + info.stake = depositInfo.stake; + info.unstakeDelaySec = depositInfo.unstakeDelaySec; + } + + /// @inheritdoc IStakeManager + function balanceOf(address account) public view returns (uint256) { + return deposits[account].deposit; + } + + receive() external payable { + depositTo(msg.sender); + } + + + /** + * Increments an account's deposit. + * @param account - The account to increment. + * @param amount - The amount to increment by. + * @return the updated deposit of this account + */ + function _incrementDeposit(address account, uint256 amount) internal returns (uint256) { + unchecked { + DepositInfo storage info = deposits[account]; + uint256 newAmount = info.deposit + amount; + info.deposit = newAmount; + return newAmount; + } + } + + /** + * Try to decrement the account's deposit. + * @param account - The account to decrement. + * @param amount - The amount to decrement by. + * @return true if the decrement succeeded (that is, previous balance was at least that amount) + */ + function _tryDecrementDeposit(address account, uint256 amount) internal returns(bool) { + unchecked { + DepositInfo storage info = deposits[account]; + uint256 currentDeposit = info.deposit; + if (currentDeposit < amount) { + return false; + } + info.deposit = currentDeposit - amount; + return true; + } + } + + /// @inheritdoc IStakeManager + function depositTo(address account) public virtual payable { + uint256 newDeposit = _incrementDeposit(account, msg.value); + emit Deposited(account, newDeposit); + } + + /// @inheritdoc IStakeManager + function addStake(uint32 unstakeDelaySec) external payable { + DepositInfo storage info = deposits[msg.sender]; + require(unstakeDelaySec > 0, "must specify unstake delay"); + require( + unstakeDelaySec >= info.unstakeDelaySec, + "cannot decrease unstake time" + ); + uint256 stake = info.stake + msg.value; + require(stake > 0, "no stake specified"); + require(stake <= type(uint112).max, "stake overflow"); + deposits[msg.sender] = DepositInfo( + info.deposit, + true, + uint112(stake), + unstakeDelaySec, + 0 + ); + emit StakeLocked(msg.sender, stake, unstakeDelaySec); + } + + /// @inheritdoc IStakeManager + function unlockStake() external { + DepositInfo storage info = deposits[msg.sender]; + require(info.unstakeDelaySec != 0, "not staked"); + require(info.staked, "already unstaking"); + uint48 withdrawTime = uint48(block.timestamp) + info.unstakeDelaySec; + info.withdrawTime = withdrawTime; + info.staked = false; + emit StakeUnlocked(msg.sender, withdrawTime); + } + + /// @inheritdoc IStakeManager + function withdrawStake(address payable withdrawAddress) external { + DepositInfo storage info = deposits[msg.sender]; + uint256 stake = info.stake; + require(stake > 0, "No stake to withdraw"); + require(info.withdrawTime > 0, "must call unlockStake() first"); + require( + info.withdrawTime <= block.timestamp, + "Stake withdrawal is not due" + ); + info.unstakeDelaySec = 0; + info.withdrawTime = 0; + info.stake = 0; + emit StakeWithdrawn(msg.sender, withdrawAddress, stake); + (bool success,) = withdrawAddress.call{value: stake}(""); + require(success, "failed to withdraw stake"); + } + + /// @inheritdoc IStakeManager + function withdrawTo( + address payable withdrawAddress, + uint256 withdrawAmount + ) external { + DepositInfo storage info = deposits[msg.sender]; + uint256 currentDeposit = info.deposit; + require(withdrawAmount <= currentDeposit, "Withdraw amount too large"); + info.deposit = currentDeposit - withdrawAmount; + emit Withdrawn(msg.sender, withdrawAddress, withdrawAmount); + (bool success,) = withdrawAddress.call{value: withdrawAmount}(""); + require(success, "failed to withdraw"); + } +} diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/UserOperationLib.sol b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/UserOperationLib.sol new file mode 100644 index 00000000..e6f50c6e --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/core/UserOperationLib.sol @@ -0,0 +1,131 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.28; + +/* solhint-disable no-inline-assembly */ + +import "../interfaces/PackedUserOperation.sol"; +import {calldataKeccak, min} from "./Helpers.sol"; + +/** + * Utility functions helpful when working with UserOperation structs. + */ +library UserOperationLib { + + uint256 public constant PAYMASTER_VALIDATION_GAS_OFFSET = 20; + uint256 public constant PAYMASTER_POSTOP_GAS_OFFSET = 36; + uint256 public constant PAYMASTER_DATA_OFFSET = 52; + + /** + * Relayer/block builder might submit the TX with higher priorityFee, + * but the user should not pay above what he signed for. + * @param userOp - The user operation data. + */ + function gasPrice( + PackedUserOperation calldata userOp + ) internal view returns (uint256) { + unchecked { + (uint256 maxPriorityFeePerGas, uint256 maxFeePerGas) = unpackUints(userOp.gasFees); + return min(maxFeePerGas, maxPriorityFeePerGas + block.basefee); + } + } + + bytes32 internal constant PACKED_USEROP_TYPEHASH = + keccak256( + "PackedUserOperation(address sender,uint256 nonce,bytes initCode,bytes callData,bytes32 accountGasLimits,uint256 preVerificationGas,bytes32 gasFees,bytes paymasterAndData)" + ); + + /** + * Pack the user operation data into bytes for hashing. + * @param userOp - The user operation data. + * @param overrideInitCodeHash - If set, encode this instead of the initCode field in the userOp. + */ + function encode( + PackedUserOperation calldata userOp, + bytes32 overrideInitCodeHash + ) internal pure returns (bytes memory ret) { + address sender = userOp.sender; + uint256 nonce = userOp.nonce; + bytes32 hashInitCode = overrideInitCodeHash != 0 ? overrideInitCodeHash : calldataKeccak(userOp.initCode); + bytes32 hashCallData = calldataKeccak(userOp.callData); + bytes32 accountGasLimits = userOp.accountGasLimits; + uint256 preVerificationGas = userOp.preVerificationGas; + bytes32 gasFees = userOp.gasFees; + bytes32 hashPaymasterAndData = calldataKeccak(userOp.paymasterAndData); + + return abi.encode( + UserOperationLib.PACKED_USEROP_TYPEHASH, + sender, nonce, + hashInitCode, hashCallData, + accountGasLimits, preVerificationGas, gasFees, + hashPaymasterAndData + ); + } + + function unpackUints( + bytes32 packed + ) internal pure returns (uint256 high128, uint256 low128) { + return (unpackHigh128(packed), unpackLow128(packed)); + } + + // Unpack just the high 128-bits from a packed value + function unpackHigh128(bytes32 packed) internal pure returns (uint256) { + return uint256(packed) >> 128; + } + + // Unpack just the low 128-bits from a packed value + function unpackLow128(bytes32 packed) internal pure returns (uint256) { + return uint128(uint256(packed)); + } + + function unpackMaxPriorityFeePerGas(PackedUserOperation calldata userOp) + internal pure returns (uint256) { + return unpackHigh128(userOp.gasFees); + } + + function unpackMaxFeePerGas(PackedUserOperation calldata userOp) + internal pure returns (uint256) { + return unpackLow128(userOp.gasFees); + } + + function unpackVerificationGasLimit(PackedUserOperation calldata userOp) + internal pure returns (uint256) { + return unpackHigh128(userOp.accountGasLimits); + } + + function unpackCallGasLimit(PackedUserOperation calldata userOp) + internal pure returns (uint256) { + return unpackLow128(userOp.accountGasLimits); + } + + function unpackPaymasterVerificationGasLimit(PackedUserOperation calldata userOp) + internal pure returns (uint256) { + return uint128(bytes16(userOp.paymasterAndData[PAYMASTER_VALIDATION_GAS_OFFSET : PAYMASTER_POSTOP_GAS_OFFSET])); + } + + function unpackPostOpGasLimit(PackedUserOperation calldata userOp) + internal pure returns (uint256) { + return uint128(bytes16(userOp.paymasterAndData[PAYMASTER_POSTOP_GAS_OFFSET : PAYMASTER_DATA_OFFSET])); + } + + function unpackPaymasterStaticFields( + bytes calldata paymasterAndData + ) internal pure returns (address paymaster, uint256 validationGasLimit, uint256 postOpGasLimit) { + return ( + address(bytes20(paymasterAndData[: PAYMASTER_VALIDATION_GAS_OFFSET])), + uint128(bytes16(paymasterAndData[PAYMASTER_VALIDATION_GAS_OFFSET : PAYMASTER_POSTOP_GAS_OFFSET])), + uint128(bytes16(paymasterAndData[PAYMASTER_POSTOP_GAS_OFFSET : PAYMASTER_DATA_OFFSET])) + ); + } + + /** + * Hash the user operation data. + * @param userOp - The user operation data. + * @param overrideInitCodeHash - If set, the initCode hash will be replaced with this value just for UserOp hashing. + */ + function hash( + PackedUserOperation calldata userOp, + bytes32 overrideInitCodeHash + ) internal pure returns (bytes32) { + return keccak256(encode(userOp, overrideInitCodeHash)); + } +} diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/interfaces/IAccount.sol b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/interfaces/IAccount.sol new file mode 100644 index 00000000..e396ba8b --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/interfaces/IAccount.sol @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.28; + +import "./PackedUserOperation.sol"; + +interface IAccount { + /** + * Validate user's signature and nonce + * the entryPoint will make the call to the recipient only if this validation call returns successfully. + * signature failure should be reported by returning SIG_VALIDATION_FAILED (1). + * This allows making a "simulation call" without a valid signature + * Other failures (e.g. nonce mismatch, or invalid signature format) should still revert to signal failure. + * + * @dev Must validate caller is the entryPoint. + * Must validate the signature and nonce + * @param userOp - The operation that is about to be executed. + * @param userOpHash - Hash of the user's request data. can be used as the basis for signature. + * @param missingAccountFunds - Missing funds on the account's deposit in the entrypoint. + * This is the minimum amount to transfer to the sender(entryPoint) to be + * able to make the call. The excess is left as a deposit in the entrypoint + * for future calls. Can be withdrawn anytime using "entryPoint.withdrawTo()". + * In case there is a paymaster in the request (or the current deposit is high + * enough), this value will be zero. + * @return validationData - Packaged ValidationData structure. use `_packValidationData` and + * `_unpackValidationData` to encode and decode. + * <20-byte> aggregatorOrSigFail - 0 for valid signature, 1 to mark signature failure, + * otherwise, an address of an "aggregator" contract. + * <6-byte> validUntil - Last timestamp this operation is valid at, or 0 for "indefinitely" + * <6-byte> validAfter - First timestamp this operation is valid + * If an account doesn't use time-range, it is enough to + * return SIG_VALIDATION_FAILED value (1) for signature failure. + * Note that the validation code cannot use block.timestamp (or block.number) directly. + */ + function validateUserOp( + PackedUserOperation calldata userOp, + bytes32 userOpHash, + uint256 missingAccountFunds + ) external returns (uint256 validationData); +} diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/interfaces/IAccountExecute.sol b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/interfaces/IAccountExecute.sol new file mode 100644 index 00000000..15e40501 --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/interfaces/IAccountExecute.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.28; + +import "./PackedUserOperation.sol"; + +interface IAccountExecute { + /** + * Account may implement this execute method. + * passing this methodSig at the beginning of callData will cause the entryPoint to pass the full UserOp (and hash) + * to the account. + * The account should skip the methodSig, and use the callData (and optionally, other UserOp fields) + * + * @param userOp - The operation that was just validated. + * @param userOpHash - Hash of the user's request data. + */ + function executeUserOp( + PackedUserOperation calldata userOp, + bytes32 userOpHash + ) external; +} diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/interfaces/IAggregator.sol b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/interfaces/IAggregator.sol new file mode 100644 index 00000000..c320cac5 --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/interfaces/IAggregator.sol @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.28; + +import "./PackedUserOperation.sol"; + +/** + * Aggregated Signatures validator. + */ +interface IAggregator { + /** + * Validate an aggregated signature. + * Reverts if the aggregated signature does not match the given list of operations. + * @param userOps - An array of UserOperations to validate the signature for. + * @param signature - The aggregated signature. + */ + function validateSignatures( + PackedUserOperation[] calldata userOps, + bytes calldata signature + ) external; + + /** + * Validate the signature of a single userOp. + * This method should be called by bundler after EntryPointSimulation.simulateValidation() returns + * the aggregator this account uses. + * First it validates the signature over the userOp. Then it returns data to be used when creating the handleOps. + * @param userOp - The userOperation received from the user. + * @return sigForUserOp - The value to put into the signature field of the userOp when calling handleOps. + * (usually empty, unless account and aggregator support some kind of "multisig". + */ + function validateUserOpSignature( + PackedUserOperation calldata userOp + ) external view returns (bytes memory sigForUserOp); + + /** + * Aggregate multiple signatures into a single value. + * This method is called off-chain to calculate the signature to pass with handleOps() + * bundler MAY use optimized custom code to perform this aggregation. + * @param userOps - An array of UserOperations to collect the signatures from. + * @return aggregatedSignature - The aggregated signature. + */ + function aggregateSignatures( + PackedUserOperation[] calldata userOps + ) external view returns (bytes memory aggregatedSignature); +} diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/interfaces/IEntryPoint.sol b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/interfaces/IEntryPoint.sol new file mode 100644 index 00000000..81f7ca3a --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/interfaces/IEntryPoint.sol @@ -0,0 +1,222 @@ +/** + ** Account-Abstraction (EIP-4337) singleton EntryPoint implementation. + ** Only one instance required on each chain. + **/ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.28; + +/* solhint-disable avoid-low-level-calls */ +/* solhint-disable no-inline-assembly */ +/* solhint-disable reason-string */ + +import "./PackedUserOperation.sol"; +import "./IStakeManager.sol"; +import "./IAggregator.sol"; +import "./INonceManager.sol"; +import "./ISenderCreator.sol"; + +interface IEntryPoint is IStakeManager, INonceManager { + /*** + * An event emitted after each successful request. + * @param userOpHash - Unique identifier for the request (hash its entire content, except signature). + * @param sender - The account that generates this request. + * @param paymaster - If non-null, the paymaster that pays for this request. + * @param nonce - The nonce value from the request. + * @param success - True if the sender transaction succeeded, false if reverted. + * @param actualGasCost - Actual amount paid (by account or paymaster) for this UserOperation. + * @param actualGasUsed - Total gas used by this UserOperation (including preVerification, creation, + * validation and execution). + */ + event UserOperationEvent( + bytes32 indexed userOpHash, + address indexed sender, + address indexed paymaster, + uint256 nonce, + bool success, + uint256 actualGasCost, + uint256 actualGasUsed + ); + + /** + * Account "sender" was deployed. + * @param userOpHash - The userOp that deployed this account. UserOperationEvent will follow. + * @param sender - The account that is deployed + * @param factory - The factory used to deploy this account (in the initCode) + * @param paymaster - The paymaster used by this UserOp + */ + event AccountDeployed( + bytes32 indexed userOpHash, + address indexed sender, + address factory, + address paymaster + ); + + /** + * An event emitted if the UserOperation "callData" reverted with non-zero length. + * @param userOpHash - The request unique identifier. + * @param sender - The sender of this request. + * @param nonce - The nonce used in the request. + * @param revertReason - The return bytes from the reverted "callData" call. + */ + event UserOperationRevertReason( + bytes32 indexed userOpHash, + address indexed sender, + uint256 nonce, + bytes revertReason + ); + + /** + * An event emitted if the UserOperation Paymaster's "postOp" call reverted with non-zero length. + * @param userOpHash - The request unique identifier. + * @param sender - The sender of this request. + * @param nonce - The nonce used in the request. + * @param revertReason - The return bytes from the reverted call to "postOp". + */ + event PostOpRevertReason( + bytes32 indexed userOpHash, + address indexed sender, + uint256 nonce, + bytes revertReason + ); + + /** + * UserOp consumed more than prefund. The UserOperation is reverted, and no refund is made. + * @param userOpHash - The request unique identifier. + * @param sender - The sender of this request. + * @param nonce - The nonce used in the request. + */ + event UserOperationPrefundTooLow( + bytes32 indexed userOpHash, + address indexed sender, + uint256 nonce + ); + + /** + * An event emitted by handleOps() and handleAggregatedOps(), before starting the execution loop. + * Any event emitted before this event, is part of the validation. + */ + event BeforeExecution(); + + /** + * Signature aggregator used by the following UserOperationEvents within this bundle. + * @param aggregator - The aggregator used for the following UserOperationEvents. + */ + event SignatureAggregatorChanged(address indexed aggregator); + + /** + * A custom revert error of handleOps andhandleAggregatedOps, to identify the offending op. + * Should be caught in off-chain handleOps/handleAggregatedOps simulation and not happen on-chain. + * Useful for mitigating DoS attempts against batchers or for troubleshooting of factory/account/paymaster reverts. + * NOTE: If simulateValidation passes successfully, there should be no reason for handleOps to fail on it. + * @param opIndex - Index into the array of ops to the failed one (in simulateValidation, this is always zero). + * @param reason - Revert reason. The string starts with a unique code "AAmn", + * where "m" is "1" for factory, "2" for account and "3" for paymaster issues, + * so a failure can be attributed to the correct entity. + */ + error FailedOp(uint256 opIndex, string reason); + + /** + * A custom revert error of handleOps and handleAggregatedOps, to report a revert by account or paymaster. + * @param opIndex - Index into the array of ops to the failed one (in simulateValidation, this is always zero). + * @param reason - Revert reason. see FailedOp(uint256,string), above + * @param inner - data from inner cought revert reason + * @dev note that inner is truncated to 2048 bytes + */ + error FailedOpWithRevert(uint256 opIndex, string reason, bytes inner); + + error PostOpReverted(bytes returnData); + + /** + * Error case when a signature aggregator fails to verify the aggregated signature it had created. + * @param aggregator The aggregator that failed to verify the signature + */ + error SignatureValidationFailed(address aggregator); + + // Return value of getSenderAddress. + error SenderAddressResult(address sender); + + // UserOps handled, per aggregator. + struct UserOpsPerAggregator { + PackedUserOperation[] userOps; + // Aggregator address + IAggregator aggregator; + // Aggregated signature + bytes signature; + } + + /** + * Execute a batch of UserOperations. + * No signature aggregator is used. + * If any account requires an aggregator (that is, it returned an aggregator when + * performing simulateValidation), then handleAggregatedOps() must be used instead. + * @param ops - The operations to execute. + * @param beneficiary - The address to receive the fees. + */ + function handleOps( + PackedUserOperation[] calldata ops, + address payable beneficiary + ) external; + + /** + * Execute a batch of UserOperation with Aggregators + * @param opsPerAggregator - The operations to execute, grouped by aggregator (or address(0) for no-aggregator accounts). + * @param beneficiary - The address to receive the fees. + */ + function handleAggregatedOps( + UserOpsPerAggregator[] calldata opsPerAggregator, + address payable beneficiary + ) external; + + /** + * Generate a request Id - unique identifier for this request. + * The request ID is a hash over the content of the userOp (except the signature), entrypoint address, chainId and (optionally) 7702 delegate address + * @param userOp - The user operation to generate the request ID for. + * @return hash the hash of this UserOperation + */ + function getUserOpHash( + PackedUserOperation calldata userOp + ) external view returns (bytes32); + + /** + * Gas and return values during simulation. + * @param preOpGas - The gas used for validation (including preValidationGas) + * @param prefund - The required prefund for this operation + * @param accountValidationData - returned validationData from account. + * @param paymasterValidationData - return validationData from paymaster. + * @param paymasterContext - Returned by validatePaymasterUserOp (to be passed into postOp) + */ + struct ReturnInfo { + uint256 preOpGas; + uint256 prefund; + uint256 accountValidationData; + uint256 paymasterValidationData; + bytes paymasterContext; + } + + /** + * Get counterfactual sender address. + * Calculate the sender contract address that will be generated by the initCode and salt in the UserOperation. + * This method always revert, and returns the address in SenderAddressResult error. + * @notice this method cannot be used for EIP-7702 derived contracts. + * + * @param initCode - The constructor code to be passed into the UserOperation. + */ + function getSenderAddress(bytes memory initCode) external; + + error DelegateAndRevert(bool success, bytes ret); + + /** + * Helper method for dry-run testing. + * @dev calling this method, the EntryPoint will make a delegatecall to the given data, and report (via revert) the result. + * The method always revert, so is only useful off-chain for dry run calls, in cases where state-override to replace + * actual EntryPoint code is less convenient. + * @param target a target contract to make a delegatecall from entrypoint + * @param data data to pass to target in a delegatecall + */ + function delegateAndRevert(address target, bytes calldata data) external; + + /** + * @notice Retrieves the immutable SenderCreator contract which is responsible for deployment of sender contracts. + */ + function senderCreator() external view returns (ISenderCreator); +} diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/interfaces/IEntryPointSimulations.sol b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/interfaces/IEntryPointSimulations.sol new file mode 100644 index 00000000..60cab7d3 --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/interfaces/IEntryPointSimulations.sol @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.28; + +import "./PackedUserOperation.sol"; +import "./IEntryPoint.sol"; + +interface IEntryPointSimulations is IEntryPoint { + // Return value of simulateHandleOp. + struct ExecutionResult { + uint256 preOpGas; + uint256 paid; + uint256 accountValidationData; + uint256 paymasterValidationData; + bool targetSuccess; + bytes targetResult; + } + + /** + * Returned aggregated signature info: + * The aggregator returned by the account, and its current stake. + */ + struct AggregatorStakeInfo { + address aggregator; + StakeInfo stakeInfo; + } + + /** + * Successful result from simulateValidation. + * If the account returns a signature aggregator the "aggregatorInfo" struct is filled in as well. + * @param returnInfo Gas and time-range returned values + * @param senderInfo Stake information about the sender + * @param factoryInfo Stake information about the factory (if any) + * @param paymasterInfo Stake information about the paymaster (if any) + * @param aggregatorInfo Signature aggregation info (if the account requires signature aggregator) + * Bundler MUST use it to verify the signature, or reject the UserOperation. + */ + struct ValidationResult { + ReturnInfo returnInfo; + StakeInfo senderInfo; + StakeInfo factoryInfo; + StakeInfo paymasterInfo; + AggregatorStakeInfo aggregatorInfo; + } + + /** + * Simulate a call to account.validateUserOp and paymaster.validatePaymasterUserOp. + * @dev The node must also verify it doesn't use banned opcodes, and that it doesn't reference storage + * outside the account's data. + * @param userOp - The user operation to validate. + * @return the validation result structure + */ + function simulateValidation( + PackedUserOperation calldata userOp + ) + external + returns ( + ValidationResult memory + ); + + /** + * Simulate full execution of a UserOperation (including both validation and target execution) + * It performs full validation of the UserOperation, but ignores signature error. + * An optional target address is called after the userop succeeds, + * and its value is returned (before the entire call is reverted). + * Note that in order to collect the the success/failure of the target call, it must be executed + * with trace enabled to track the emitted events. + * @param op The UserOperation to simulate. + * @param target - If nonzero, a target address to call after userop simulation. If called, + * the targetSuccess and targetResult are set to the return from that call. + * @param targetCallData - CallData to pass to target address. + * @return the execution result structure + */ + function simulateHandleOp( + PackedUserOperation calldata op, + address target, + bytes calldata targetCallData + ) + external + returns ( + ExecutionResult memory + ); +} diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/interfaces/INonceManager.sol b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/interfaces/INonceManager.sol new file mode 100644 index 00000000..8f2cb1b9 --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/interfaces/INonceManager.sol @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.28; + +interface INonceManager { + + /** + * Return the next nonce for this sender. + * Within a given key, the nonce values are sequenced (starting with zero, and incremented by one on each userop) + * But UserOp with different keys can come with arbitrary order. + * + * @param sender the account address + * @param key the high 192 bit of the nonce + * @return nonce a full nonce to pass for next UserOp with this sender. + */ + function getNonce(address sender, uint192 key) + external view returns (uint256 nonce); + + /** + * Manually increment the nonce of the sender. + * This method is exposed just for completeness.. + * Account does NOT need to call it, neither during validation, nor elsewhere, + * as the EntryPoint will update the nonce regardless. + * Possible use-case is call it with various keys to "initialize" their nonces to one, so that future + * UserOperations will not pay extra for the first transaction with a given key. + * + * @param key - the "nonce key" to increment the "nonce sequence" for. + */ + function incrementNonce(uint192 key) external; +} diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/interfaces/IPaymaster.sol b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/interfaces/IPaymaster.sol new file mode 100644 index 00000000..4a1364a4 --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/interfaces/IPaymaster.sol @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.28; + +import "./PackedUserOperation.sol"; + +/** + * The interface exposed by a paymaster contract, who agrees to pay the gas for user's operations. + * A paymaster must hold a stake to cover the required entrypoint stake and also the gas for the transaction. + */ +interface IPaymaster { + enum PostOpMode { + // User op succeeded. + opSucceeded, + // User op reverted. Still has to pay for gas. + opReverted, + // Only used internally in the EntryPoint (cleanup after postOp reverts). Never calling paymaster with this value + postOpReverted + } + + /** + * Payment validation: check if paymaster agrees to pay. + * Must verify sender is the entryPoint. + * Revert to reject this request. + * Note that bundlers will reject this method if it changes the state, unless the paymaster is trusted (whitelisted). + * The paymaster pre-pays using its deposit, and receive back a refund after the postOp method returns. + * @param userOp - The user operation. + * @param userOpHash - Hash of the user's request data. + * @param maxCost - The maximum cost of this transaction (based on maximum gas and gas price from userOp). + * @return context - Value to send to a postOp. Zero length to signify postOp is not required. + * @return validationData - Signature and time-range of this operation, encoded the same as the return + * value of validateUserOperation. + * <20-byte> aggregatorOrSigFail - 0 for valid signature, 1 to mark signature failure, + * other values are invalid for paymaster. + * <6-byte> validUntil - Last timestamp this operation is valid at, or 0 for "indefinitely" + * <6-byte> validAfter - first timestamp this operation is valid + * Note that the validation code cannot use block.timestamp (or block.number) directly. + */ + function validatePaymasterUserOp( + PackedUserOperation calldata userOp, + bytes32 userOpHash, + uint256 maxCost + ) external returns (bytes memory context, uint256 validationData); + + /** + * Post-operation handler. + * Must verify sender is the entryPoint. + * @param mode - Enum with the following options: + * opSucceeded - User operation succeeded. + * opReverted - User op reverted. The paymaster still has to pay for gas. + * postOpReverted - never passed in a call to postOp(). + * @param context - The context value returned by validatePaymasterUserOp + * @param actualGasCost - Actual cost of gas used so far (without this postOp call). + * @param actualUserOpFeePerGas - the gas price this UserOp pays. This value is based on the UserOp's maxFeePerGas + * and maxPriorityFee (and basefee) + * It is not the same as tx.gasprice, which is what the bundler pays. + */ + function postOp( + PostOpMode mode, + bytes calldata context, + uint256 actualGasCost, + uint256 actualUserOpFeePerGas + ) external; +} diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/interfaces/ISenderCreator.sol b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/interfaces/ISenderCreator.sol new file mode 100644 index 00000000..68d867a6 --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/interfaces/ISenderCreator.sol @@ -0,0 +1,21 @@ + +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.28; + +interface ISenderCreator { + /** + * @dev Creates a new sender contract. + * @return sender Address of the newly created sender contract. + */ + function createSender(bytes calldata initCode) external returns (address sender); + + /** + * Use initCallData to initialize an EIP-7702 account. + * The caller is the EntryPoint contract and it is already verified to be an EIP-7702 account. + * Note: Can be called multiple times as long as an appropriate initCode is supplied + * + * @param sender - the 'sender' EIP-7702 account to be initialized. + * @param initCallData - the call data to be passed to the sender account call. + */ + function initEip7702Sender(address sender, bytes calldata initCallData) external; +} diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/interfaces/IStakeManager.sol b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/interfaces/IStakeManager.sol new file mode 100644 index 00000000..8128feba --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/interfaces/IStakeManager.sol @@ -0,0 +1,111 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.28; + +/** + * Manage deposits and stakes. + * Deposit is just a balance used to pay for UserOperations (either by a paymaster or an account). + * Stake is value locked for at least "unstakeDelay" by the staked entity. + */ +interface IStakeManager { + event Deposited(address indexed account, uint256 totalDeposit); + + event Withdrawn( + address indexed account, + address withdrawAddress, + uint256 amount + ); + + // Emitted when stake or unstake delay are modified. + event StakeLocked( + address indexed account, + uint256 totalStaked, + uint256 unstakeDelaySec + ); + + // Emitted once a stake is scheduled for withdrawal. + event StakeUnlocked(address indexed account, uint256 withdrawTime); + + event StakeWithdrawn( + address indexed account, + address withdrawAddress, + uint256 amount + ); + + /** + * @param deposit - The entity's deposit. + * @param staked - True if this entity is staked. + * @param stake - Actual amount of ether staked for this entity. + * @param unstakeDelaySec - Minimum delay to withdraw the stake. + * @param withdrawTime - First block timestamp where 'withdrawStake' will be callable, or zero if already locked. + * @dev Sizes were chosen so that deposit fits into one cell (used during handleOp) + * and the rest fit into a 2nd cell (used during stake/unstake) + * - 112 bit allows for 10^15 eth + * - 48 bit for full timestamp + * - 32 bit allows 150 years for unstake delay + */ + struct DepositInfo { + uint256 deposit; + bool staked; + uint112 stake; + uint32 unstakeDelaySec; + uint48 withdrawTime; + } + + // API struct used by getStakeInfo and simulateValidation. + struct StakeInfo { + uint256 stake; + uint256 unstakeDelaySec; + } + + /** + * Get deposit info. + * @param account - The account to query. + * @return info - Full deposit information of given account. + */ + function getDepositInfo( + address account + ) external view returns (DepositInfo memory info); + + /** + * Get account balance. + * @param account - The account to query. + * @return - The deposit (for gas payment) of the account. + */ + function balanceOf(address account) external view returns (uint256); + + /** + * Add to the deposit of the given account. + * @param account - The account to add to. + */ + function depositTo(address account) external payable; + + /** + * Add to the account's stake - amount and delay + * any pending unstake is first cancelled. + * @param unstakeDelaySec - The new lock duration before the deposit can be withdrawn. + */ + function addStake(uint32 unstakeDelaySec) external payable; + + /** + * Attempt to unlock the stake. + * The value can be withdrawn (using withdrawStake) after the unstake delay. + */ + function unlockStake() external; + + /** + * Withdraw from the (unlocked) stake. + * Must first call unlockStake and wait for the unstakeDelay to pass. + * @param withdrawAddress - The address to send withdrawn value. + */ + function withdrawStake(address payable withdrawAddress) external; + + /** + * Withdraw from the deposit. + * @param withdrawAddress - The address to send withdrawn value. + * @param withdrawAmount - The amount to withdraw. + */ + function withdrawTo( + address payable withdrawAddress, + uint256 withdrawAmount + ) external; +} diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/interfaces/PackedUserOperation.sol b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/interfaces/PackedUserOperation.sol new file mode 100644 index 00000000..eb12fb75 --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/interfaces/PackedUserOperation.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.28; + +/** + * User Operation struct + * @param sender - The sender account of this request. + * @param nonce - Unique value the sender uses to verify it is not a replay. + * @param initCode - If set, the account contract will be created by this constructor + * @param callData - The method call to execute on this account. + * @param accountGasLimits - Packed gas limits for validateUserOp and gas limit passed to the callData method call. + * @param preVerificationGas - Gas not calculated by the handleOps method, but added to the gas paid. + * Covers batch overhead. + * @param gasFees - packed gas fields maxPriorityFeePerGas and maxFeePerGas - Same as EIP-1559 gas parameters. + * @param paymasterAndData - If set, this field holds the paymaster address, verification gas limit, postOp gas limit and paymaster-specific extra data + * The paymaster will pay for the transaction instead of the sender. + * @param signature - Sender-verified signature over the entire request, the EntryPoint address and the chain ID. + */ +struct PackedUserOperation { + address sender; + uint256 nonce; + bytes initCode; + bytes callData; + bytes32 accountGasLimits; + uint256 preVerificationGas; + bytes32 gasFees; + bytes paymasterAndData; + bytes signature; +} diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/legacy/v06/IAccount06.sol b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/legacy/v06/IAccount06.sol new file mode 100644 index 00000000..a8c4bda9 --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/legacy/v06/IAccount06.sol @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.12; + +import "./UserOperation06.sol"; + +interface IAccount06 { + + /** + * Validate user's signature and nonce + * the entryPoint will make the call to the recipient only if this validation call returns successfully. + * signature failure should be reported by returning SIG_VALIDATION_FAILED (1). + * This allows making a "simulation call" without a valid signature + * Other failures (e.g. nonce mismatch, or invalid signature format) should still revert to signal failure. + * + * @dev Must validate caller is the entryPoint. + * Must validate the signature and nonce + * @param userOp the operation that is about to be executed. + * @param userOpHash hash of the user's request data. can be used as the basis for signature. + * @param missingAccountFunds missing funds on the account's deposit in the entrypoint. + * This is the minimum amount to transfer to the sender(entryPoint) to be able to make the call. + * The excess is left as a deposit in the entrypoint, for future calls. + * can be withdrawn anytime using "entryPoint.withdrawTo()" + * In case there is a paymaster in the request (or the current deposit is high enough), this value will be zero. + * @return validationData packaged ValidationData structure. use `_packValidationData` and `_unpackValidationData` to encode and decode + * <20-byte> sigAuthorizer - 0 for valid signature, 1 to mark signature failure, + * otherwise, an address of an "authorizer" contract. + * <6-byte> validUntil - last timestamp this operation is valid. 0 for "indefinite" + * <6-byte> validAfter - first timestamp this operation is valid + * If an account doesn't use time-range, it is enough to return SIG_VALIDATION_FAILED value (1) for signature failure. + * Note that the validation code cannot use block.timestamp (or block.number) directly. + */ + function validateUserOp(UserOperation06 calldata userOp, bytes32 userOpHash, uint256 missingAccountFunds) + external returns (uint256 validationData); +} diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/legacy/v06/IAggregator06.sol b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/legacy/v06/IAggregator06.sol new file mode 100644 index 00000000..dab1d304 --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/legacy/v06/IAggregator06.sol @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.12; + +import "./UserOperation06.sol"; + +/** + * Aggregated Signatures validator. + */ +interface IAggregator06 { + + /** + * validate aggregated signature. + * revert if the aggregated signature does not match the given list of operations. + */ + function validateSignatures(UserOperation06[] calldata userOps, bytes calldata signature) external view; + + /** + * validate signature of a single userOp + * This method is should be called by bundler after EntryPoint.simulateValidation() returns (reverts) with ValidationResultWithAggregation + * First it validates the signature over the userOp. Then it returns data to be used when creating the handleOps. + * @param userOp the userOperation received from the user. + * @return sigForUserOp the value to put into the signature field of the userOp when calling handleOps. + * (usually empty, unless account and aggregator support some kind of "multisig" + */ + function validateUserOpSignature(UserOperation06 calldata userOp) + external view returns (bytes memory sigForUserOp); + + /** + * aggregate multiple signatures into a single value. + * This method is called off-chain to calculate the signature to pass with handleOps() + * bundler MAY use optimized custom code perform this aggregation + * @param userOps array of UserOperations to collect the signatures from. + * @return aggregatedSignature the aggregated signature + */ + function aggregateSignatures(UserOperation06[] calldata userOps) external view returns (bytes memory aggregatedSignature); +} diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/legacy/v06/IEntryPoint06.sol b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/legacy/v06/IEntryPoint06.sol new file mode 100644 index 00000000..6b53fd6a --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/legacy/v06/IEntryPoint06.sol @@ -0,0 +1,204 @@ +/** + ** Account-Abstraction (EIP-4337) singleton EntryPoint implementation. + ** Only one instance required on each chain. + **/ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.12; + +/* solhint-disable avoid-low-level-calls */ +/* solhint-disable no-inline-assembly */ +/* solhint-disable reason-string */ + +import "./UserOperation06.sol"; +import "./IStakeManager06.sol"; +import "./IAggregator06.sol"; +import "./INonceManager06.sol"; + +interface IEntryPoint is IStakeManager06, INonceManager06 { + + /*** + * An event emitted after each successful request + * @param userOpHash - unique identifier for the request (hash its entire content, except signature). + * @param sender - the account that generates this request. + * @param paymaster - if non-null, the paymaster that pays for this request. + * @param nonce - the nonce value from the request. + * @param success - true if the sender transaction succeeded, false if reverted. + * @param actualGasCost - actual amount paid (by account or paymaster) for this UserOperation. + * @param actualGasUsed - total gas used by this UserOperation (including preVerification, creation, validation and execution). + */ + event UserOperationEvent(bytes32 indexed userOpHash, address indexed sender, address indexed paymaster, uint256 nonce, bool success, uint256 actualGasCost, uint256 actualGasUsed); + + /** + * account "sender" was deployed. + * @param userOpHash the userOp that deployed this account. UserOperationEvent will follow. + * @param sender the account that is deployed + * @param factory the factory used to deploy this account (in the initCode) + * @param paymaster the paymaster used by this UserOp + */ + event AccountDeployed(bytes32 indexed userOpHash, address indexed sender, address factory, address paymaster); + + /** + * An event emitted if the UserOperation "callData" reverted with non-zero length + * @param userOpHash the request unique identifier. + * @param sender the sender of this request + * @param nonce the nonce used in the request + * @param revertReason - the return bytes from the (reverted) call to "callData". + */ + event UserOperationRevertReason(bytes32 indexed userOpHash, address indexed sender, uint256 nonce, bytes revertReason); + + /** + * an event emitted by handleOps(), before starting the execution loop. + * any event emitted before this event, is part of the validation. + */ + event BeforeExecution(); + + /** + * signature aggregator used by the following UserOperationEvents within this bundle. + */ + event SignatureAggregatorChanged(address indexed aggregator); + + /** + * a custom revert error of handleOps, to identify the offending op. + * NOTE: if simulateValidation passes successfully, there should be no reason for handleOps to fail on it. + * @param opIndex - index into the array of ops to the failed one (in simulateValidation, this is always zero) + * @param reason - revert reason + * The string starts with a unique code "AAmn", where "m" is "1" for factory, "2" for account and "3" for paymaster issues, + * so a failure can be attributed to the correct entity. + * Should be caught in off-chain handleOps simulation and not happen on-chain. + * Useful for mitigating DoS attempts against batchers or for troubleshooting of factory/account/paymaster reverts. + */ + error FailedOp(uint256 opIndex, string reason); + + /** + * error case when a signature aggregator fails to verify the aggregated signature it had created. + */ + error SignatureValidationFailed(address aggregator); + + /** + * Successful result from simulateValidation. + * @param returnInfo gas and time-range returned values + * @param senderInfo stake information about the sender + * @param factoryInfo stake information about the factory (if any) + * @param paymasterInfo stake information about the paymaster (if any) + */ + error ValidationResult(ReturnInfo returnInfo, + StakeInfo senderInfo, StakeInfo factoryInfo, StakeInfo paymasterInfo); + + /** + * Successful result from simulateValidation, if the account returns a signature aggregator + * @param returnInfo gas and time-range returned values + * @param senderInfo stake information about the sender + * @param factoryInfo stake information about the factory (if any) + * @param paymasterInfo stake information about the paymaster (if any) + * @param aggregatorInfo signature aggregation info (if the account requires signature aggregator) + * bundler MUST use it to verify the signature, or reject the UserOperation + */ + error ValidationResultWithAggregation(ReturnInfo returnInfo, + StakeInfo senderInfo, StakeInfo factoryInfo, StakeInfo paymasterInfo, + AggregatorStakeInfo aggregatorInfo); + + /** + * return value of getSenderAddress + */ + error SenderAddressResult(address sender); + + /** + * return value of simulateHandleOp + */ + error ExecutionResult(uint256 preOpGas, uint256 paid, uint48 validAfter, uint48 validUntil, bool targetSuccess, bytes targetResult); + + // UserOps handled, per aggregator + struct UserOpsPerAggregator { + UserOperation06[] userOps; + + // aggregator address + IAggregator06 aggregator; + // aggregated signature + bytes signature; + } + + /** + * Execute a batch of UserOperation. + * no signature aggregator is used. + * if any account requires an aggregator (that is, it returned an aggregator when + * performing simulateValidation), then handleAggregatedOps() must be used instead. + * @param ops the operations to execute + * @param beneficiary the address to receive the fees + */ + function handleOps(UserOperation06[] calldata ops, address payable beneficiary) external; + + /** + * Execute a batch of UserOperation with Aggregators + * @param opsPerAggregator the operations to execute, grouped by aggregator (or address(0) for no-aggregator accounts) + * @param beneficiary the address to receive the fees + */ + function handleAggregatedOps( + UserOpsPerAggregator[] calldata opsPerAggregator, + address payable beneficiary + ) external; + + /** + * generate a request Id - unique identifier for this request. + * the request ID is a hash over the content of the userOp (except the signature), the entrypoint and the chainid. + */ + function getUserOpHash(UserOperation06 calldata userOp) external view returns (bytes32); + + /** + * Simulate a call to account.validateUserOp and paymaster.validatePaymasterUserOp. + * @dev this method always revert. Successful result is ValidationResult error. other errors are failures. + * @dev The node must also verify it doesn't use banned opcodes, and that it doesn't reference storage outside the account's data. + * @param userOp the user operation to validate. + */ + function simulateValidation(UserOperation06 calldata userOp) external; + + /** + * gas and return values during simulation + * @param preOpGas the gas used for validation (including preValidationGas) + * @param prefund the required prefund for this operation + * @param sigFailed validateUserOp's (or paymaster's) signature check failed + * @param validAfter - first timestamp this UserOp is valid (merging account and paymaster time-range) + * @param validUntil - last timestamp this UserOp is valid (merging account and paymaster time-range) + * @param paymasterContext returned by validatePaymasterUserOp (to be passed into postOp) + */ + struct ReturnInfo { + uint256 preOpGas; + uint256 prefund; + bool sigFailed; + uint48 validAfter; + uint48 validUntil; + bytes paymasterContext; + } + + /** + * returned aggregated signature info. + * the aggregator returned by the account, and its current stake. + */ + struct AggregatorStakeInfo { + address aggregator; + StakeInfo stakeInfo; + } + + /** + * Get counterfactual sender address. + * Calculate the sender contract address that will be generated by the initCode and salt in the UserOperation. + * this method always revert, and returns the address in SenderAddressResult error + * @param initCode the constructor code to be passed into the UserOperation. + */ + function getSenderAddress(bytes memory initCode) external; + + + /** + * simulate full execution of a UserOperation (including both validation and target execution) + * this method will always revert with "ExecutionResult". + * it performs full validation of the UserOperation, but ignores signature error. + * an optional target address is called after the userop succeeds, and its value is returned + * (before the entire call is reverted) + * Note that in order to collect the the success/failure of the target call, it must be executed + * with trace enabled to track the emitted events. + * @param op the UserOperation to simulate + * @param target if nonzero, a target address to call after userop simulation. If called, the targetSuccess and targetResult + * are set to the return from that call. + * @param targetCallData callData to pass to target address + */ + function simulateHandleOp(UserOperation06 calldata op, address target, bytes calldata targetCallData) external; +} diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/legacy/v06/INonceManager06.sol b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/legacy/v06/INonceManager06.sol new file mode 100644 index 00000000..dd7f5760 --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/legacy/v06/INonceManager06.sol @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.12; + +interface INonceManager06 { + + /** + * Return the next nonce for this sender. + * Within a given key, the nonce values are sequenced (starting with zero, and incremented by one on each userop) + * But UserOp with different keys can come with arbitrary order. + * + * @param sender the account address + * @param key the high 192 bit of the nonce + * @return nonce a full nonce to pass for next UserOp with this sender. + */ + function getNonce(address sender, uint192 key) + external view returns (uint256 nonce); + + /** + * Manually increment the nonce of the sender. + * This method is exposed just for completeness.. + * Account does NOT need to call it, neither during validation, nor elsewhere, + * as the EntryPoint will update the nonce regardless. + * Possible use-case is call it with various keys to "initialize" their nonces to one, so that future + * UserOperations will not pay extra for the first transaction with a given key. + */ + function incrementNonce(uint192 key) external; +} diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/legacy/v06/IPaymaster06.sol b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/legacy/v06/IPaymaster06.sol new file mode 100644 index 00000000..e111b008 --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/legacy/v06/IPaymaster06.sol @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.12; + +import "./UserOperation06.sol"; + +/** + * the interface exposed by a paymaster contract, who agrees to pay the gas for user's operations. + * a paymaster must hold a stake to cover the required entrypoint stake and also the gas for the transaction. + */ +interface IPaymaster06 { + + enum PostOpMode { + opSucceeded, // user op succeeded + opReverted, // user op reverted. still has to pay for gas. + postOpReverted // user op succeeded, but caused postOp to revert. Now it's a 2nd call, after user's op was deliberately reverted. + } + + /** + * payment validation: check if paymaster agrees to pay. + * Must verify sender is the entryPoint. + * Revert to reject this request. + * Note that bundlers will reject this method if it changes the state, unless the paymaster is trusted (whitelisted) + * The paymaster pre-pays using its deposit, and receive back a refund after the postOp method returns. + * @param userOp the user operation + * @param userOpHash hash of the user's request data. + * @param maxCost the maximum cost of this transaction (based on maximum gas and gas price from userOp) + * @return context value to send to a postOp + * zero length to signify postOp is not required. + * @return validationData signature and time-range of this operation, encoded the same as the return value of validateUserOperation + * <20-byte> sigAuthorizer - 0 for valid signature, 1 to mark signature failure, + * otherwise, an address of an "authorizer" contract. + * <6-byte> validUntil - last timestamp this operation is valid. 0 for "indefinite" + * <6-byte> validAfter - first timestamp this operation is valid + * Note that the validation code cannot use block.timestamp (or block.number) directly. + */ + function validatePaymasterUserOp(UserOperation06 calldata userOp, bytes32 userOpHash, uint256 maxCost) + external returns (bytes memory context, uint256 validationData); + + /** + * post-operation handler. + * Must verify sender is the entryPoint + * @param mode enum with the following options: + * opSucceeded - user operation succeeded. + * opReverted - user op reverted. still has to pay for gas. + * postOpReverted - user op succeeded, but caused postOp (in mode=opSucceeded) to revert. + * Now this is the 2nd call, after user's op was deliberately reverted. + * @param context - the context value returned by validatePaymasterUserOp + * @param actualGasCost - actual gas used so far (without this postOp call). + */ + function postOp(PostOpMode mode, bytes calldata context, uint256 actualGasCost) external; +} diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/legacy/v06/IStakeManager06.sol b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/legacy/v06/IStakeManager06.sol new file mode 100644 index 00000000..c07c25fc --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/legacy/v06/IStakeManager06.sol @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.12; + +/** + * manage deposits and stakes. + * deposit is just a balance used to pay for UserOperations (either by a paymaster or an account) + * stake is value locked for at least "unstakeDelay" by the staked entity. + */ +interface IStakeManager06 { + + event Deposited( + address indexed account, + uint256 totalDeposit + ); + + event Withdrawn( + address indexed account, + address withdrawAddress, + uint256 amount + ); + + /// Emitted when stake or unstake delay are modified + event StakeLocked( + address indexed account, + uint256 totalStaked, + uint256 unstakeDelaySec + ); + + /// Emitted once a stake is scheduled for withdrawal + event StakeUnlocked( + address indexed account, + uint256 withdrawTime + ); + + event StakeWithdrawn( + address indexed account, + address withdrawAddress, + uint256 amount + ); + + /** + * @param deposit the entity's deposit + * @param staked true if this entity is staked. + * @param stake actual amount of ether staked for this entity. + * @param unstakeDelaySec minimum delay to withdraw the stake. + * @param withdrawTime - first block timestamp where 'withdrawStake' will be callable, or zero if already locked + * @dev sizes were chosen so that (deposit,staked, stake) fit into one cell (used during handleOps) + * and the rest fit into a 2nd cell. + * 112 bit allows for 10^15 eth + * 48 bit for full timestamp + * 32 bit allows 150 years for unstake delay + */ + struct DepositInfo { + uint112 deposit; + bool staked; + uint112 stake; + uint32 unstakeDelaySec; + uint48 withdrawTime; + } + + // API struct used by getStakeInfo and simulateValidation + struct StakeInfo { + uint256 stake; + uint256 unstakeDelaySec; + } + + /// @return info - full deposit information of given account + function getDepositInfo(address account) external view returns (DepositInfo memory info); + + /// @return the deposit (for gas payment) of the account + function balanceOf(address account) external view returns (uint256); + + /** + * add to the deposit of the given account + */ + function depositTo(address account) external payable; + + /** + * add to the account's stake - amount and delay + * any pending unstake is first cancelled. + * @param _unstakeDelaySec the new lock duration before the deposit can be withdrawn. + */ + function addStake(uint32 _unstakeDelaySec) external payable; + + /** + * attempt to unlock the stake. + * the value can be withdrawn (using withdrawStake) after the unstake delay. + */ + function unlockStake() external; + + /** + * withdraw from the (unlocked) stake. + * must first call unlockStake and wait for the unstakeDelay to pass + * @param withdrawAddress the address to send withdrawn value. + */ + function withdrawStake(address payable withdrawAddress) external; + + /** + * withdraw from the deposit. + * @param withdrawAddress the address to send withdrawn value. + * @param withdrawAmount the amount to withdraw. + */ + function withdrawTo(address payable withdrawAddress, uint256 withdrawAmount) external; +} diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/legacy/v06/UserOperation06.sol b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/legacy/v06/UserOperation06.sol new file mode 100644 index 00000000..1479bcc5 --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/legacy/v06/UserOperation06.sol @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.12; + +/** + * User Operation struct + * @param sender the sender account of this request. + * @param nonce unique value the sender uses to verify it is not a replay. + * @param initCode if set, the account contract will be created by this constructor/ + * @param callData the method call to execute on this account. + * @param callGasLimit the gas limit passed to the callData method call. + * @param verificationGasLimit gas used for validateUserOp and validatePaymasterUserOp. + * @param preVerificationGas gas not calculated by the handleOps method, but added to the gas paid. Covers batch overhead. + * @param maxFeePerGas same as EIP-1559 gas parameter. + * @param maxPriorityFeePerGas same as EIP-1559 gas parameter. + * @param paymasterAndData if set, this field holds the paymaster address and paymaster-specific data. the paymaster will pay for the transaction instead of the sender. + * @param signature sender-verified signature over the entire request, the EntryPoint address and the chain ID. + */ +struct UserOperation06 { + address sender; + uint256 nonce; + bytes initCode; + bytes callData; + uint256 callGasLimit; + uint256 verificationGasLimit; + uint256 preVerificationGas; + uint256 maxFeePerGas; + uint256 maxPriorityFeePerGas; + bytes paymasterAndData; + bytes signature; +} diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/GasCalcPaymasterWithPostOp.sol b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/GasCalcPaymasterWithPostOp.sol new file mode 100644 index 00000000..02a5c137 --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/GasCalcPaymasterWithPostOp.sol @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.28; + +import "./TestPaymasterAcceptAll.sol"; +/* solhint-disable no-empty-blocks */ + +/** + * test paymaster, that pays for everything, without any check. + * explicitly returns a context, to test cost (for entrypoint) to call postOp + */ +contract GasCalcPaymasterWithPostOp is TestPaymasterAcceptAll { + constructor(IEntryPoint _entryPoint) TestPaymasterAcceptAll(_entryPoint) { + } + + function _validatePaymasterUserOp(PackedUserOperation calldata, bytes32, uint256) + internal virtual override view + returns (bytes memory context, uint256 validationData) { + // return a context, to force a call for postOp. + return ("1", SIG_VALIDATION_SUCCESS); + } + + function _postOp(PostOpMode, bytes calldata, uint256 actualGasCost, uint256) + internal override { + } +} diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/MaliciousAccount.sol b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/MaliciousAccount.sol new file mode 100644 index 00000000..dbb3a2c3 --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/MaliciousAccount.sol @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.28; + +import "../interfaces/IAccount.sol"; +import "../interfaces/IEntryPoint.sol"; +import "../core/UserOperationLib.sol"; +import "../core/Helpers.sol"; + +contract MaliciousAccount is IAccount { + using UserOperationLib for PackedUserOperation; + IEntryPoint private ep; + constructor(IEntryPoint _ep) payable { + ep = _ep; + } + function validateUserOp(PackedUserOperation calldata userOp, bytes32, uint256 missingAccountFunds) + external returns (uint256 validationData) { + ep.depositTo{value: missingAccountFunds}(address(this)); + // Now calculate basefee per EntryPoint.getUserOpGasPrice() and compare it to the basefe we pass off-chain in the signature + uint256 externalBaseFee = abi.decode(userOp.signature, (uint256)); + uint256 verificationGasLimit = userOp.unpackVerificationGasLimit(); + uint256 callGasLimit = userOp.unpackCallGasLimit(); + uint256 requiredGas = verificationGasLimit + + callGasLimit + + userOp.preVerificationGas; + uint256 gasPrice = missingAccountFunds / requiredGas; + uint256 maxPriorityFeePerGas = userOp.unpackMaxPriorityFeePerGas(); + uint256 basefee = gasPrice - maxPriorityFeePerGas; + require (basefee == externalBaseFee, "Revert after first validation"); + return SIG_VALIDATION_SUCCESS; + } +} diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestAggregatedAccount.sol b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestAggregatedAccount.sol new file mode 100644 index 00000000..2442ccd8 --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestAggregatedAccount.sol @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.28; + +import "../accounts/SimpleAccount.sol"; +import "../core/Helpers.sol"; + +/** + * test aggregated-signature account. + * works only with TestAggregatedSignature, which doesn't really check signature, but nonce sum + * a true aggregated account should expose data (e.g. its public key) to the aggregator. + */ +contract TestAggregatedAccount is SimpleAccount { + address public immutable aggregator; + + // The constructor is used only for the "implementation" and only sets immutable values. + // Mutable value slots for proxy accounts are set by the 'initialize' function. + constructor(IEntryPoint anEntryPoint, address anAggregator) SimpleAccount(anEntryPoint) { + aggregator = anAggregator; + } + + /// @inheritdoc SimpleAccount + function initialize(address) public virtual override initializer { + super._initialize(address(0)); + } + + function _validateSignature(PackedUserOperation calldata userOp, bytes32 userOpHash) + internal override view returns (uint256 validationData) { + (userOp, userOpHash); + return _packValidationData(ValidationData(aggregator, 0, 0)); + } +} diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestAggregatedAccountFactory.sol b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestAggregatedAccountFactory.sol new file mode 100644 index 00000000..d1cda5e7 --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestAggregatedAccountFactory.sol @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.28; + +import "@openzeppelin/contracts/utils/Create2.sol"; +import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; + +import "./TestAggregatedAccount.sol"; + +/** + * Based on SimpleAccountFactory. + * Cannot be a subclass since both constructor and createAccount depend on the + * constructor and initializer of the actual account contract. + */ +contract TestAggregatedAccountFactory { + TestAggregatedAccount public immutable accountImplementation; + + constructor(IEntryPoint anEntryPoint, address anAggregator){ + accountImplementation = new TestAggregatedAccount(anEntryPoint, anAggregator); + } + + /** + * create an account, and return its address. + * returns the address even if the account is already deployed. + * Note that during UserOperation execution, this method is called only if the account is not deployed. + * This method returns an existing account address so that entryPoint.getSenderAddress() would work even after account creation + */ + function createAccount(address owner,uint256 salt) public returns (TestAggregatedAccount ret) { + address addr = getAddress(owner, salt); + uint256 codeSize = addr.code.length; + if (codeSize > 0) { + return TestAggregatedAccount(payable(addr)); + } + ret = TestAggregatedAccount(payable(new ERC1967Proxy{salt : bytes32(salt)}( + address(accountImplementation), + abi.encodeCall(TestAggregatedAccount.initialize, (owner)) + ))); + } + + /** + * calculate the counterfactual address of this account as it would be returned by createAccount() + */ + function getAddress(address owner,uint256 salt) public view returns (address) { + return Create2.computeAddress(bytes32(salt), keccak256(abi.encodePacked( + type(ERC1967Proxy).creationCode, + abi.encode( + address(accountImplementation), + abi.encodeCall(TestAggregatedAccount.initialize, (owner)) + ) + ))); + } +} diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestCounter.sol b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestCounter.sol new file mode 100644 index 00000000..c56a934c --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestCounter.sol @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.28; + +// Sample "receiver" contract, for testing "exec" from account. +contract TestCounter { + mapping(address => uint256) public counters; + + function count() public { + counters[msg.sender] = counters[msg.sender] + 1; + } + + function countFail() public pure { + revert("count failed"); + } + + function justemit() public { + emit CalledFrom(msg.sender); + } + + event CalledFrom(address sender); + + // Helper method to waste gas + // repeat - waste gas on writing storage in a loop + // junk - dynamic buffer to stress the function size. + mapping(uint256 => uint256) public xxx; + uint256 public offset; + + function gasWaster(uint256 repeat, string calldata /*junk*/) external { + for (uint256 i = 1; i <= repeat; i++) { + offset++; + xxx[offset] = i; + } + } +} diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestERC20.sol b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestERC20.sol new file mode 100644 index 00000000..4a167c57 --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestERC20.sol @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.28; + +import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; + +contract TestERC20 is ERC20 { + uint8 private immutable __decimals; + + constructor(uint8 _decimals) ERC20("TestERC20", "T20") { + _mint(msg.sender, 1000000000000000000000000); + __decimals = _decimals; + } + + function decimals() public view override returns (uint8) { + return __decimals; + } + + function sudoMint(address _to, uint256 _amount) external { + _mint(_to, _amount); + } + + function sudoTransfer(address _from, address _to) external { + _transfer(_from, _to, balanceOf(_from)); + } + + function sudoApprove(address _from, address _to, uint256 _amount) external { + _approve(_from, _to, _amount); + } +} diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestEip7702DelegateAccount.sol b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestEip7702DelegateAccount.sol new file mode 100644 index 00000000..cd87cbc9 --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestEip7702DelegateAccount.sol @@ -0,0 +1,23 @@ +pragma solidity ^0.8.28; +// SPDX-License-Identifier: GPL-3.0 + +import "../accounts/Simple7702Account.sol"; + +contract TestEip7702DelegateAccount is Simple7702Account { + + bool public testInitCalled; + + function testInit() public { + testInitCalled = true; + } + + function _validateSignature( + PackedUserOperation calldata userOp, + bytes32 userOpHash + ) internal virtual override returns (uint256 validationData) { + if (userOp.initCode.length > 20) { + require(testInitCalled, "testInit not called"); + } + return Simple7702Account._validateSignature(userOp, userOpHash); + } +} diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestExecAccount.sol b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestExecAccount.sol new file mode 100644 index 00000000..a3fa6a1f --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestExecAccount.sol @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: GPL-3.0 + +/* solhint-disable one-contract-per-file */ +/* solhint-disable avoid-low-level-calls */ +pragma solidity ^0.8.28; + +import "@openzeppelin/contracts/utils/Create2.sol"; +import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; + +import "../accounts/SimpleAccount.sol"; +import "../interfaces/IAccountExecute.sol"; + +/** + * a sample account with execUserOp. + * Note that this account does nothing special with the userop, just extract + * call to execute. In theory, such account can reference the signature, the hash, etc. + */ +contract TestExecAccount is SimpleAccount, IAccountExecute { + + constructor(IEntryPoint anEntryPoint) SimpleAccount(anEntryPoint){ + } + + event Executed(PackedUserOperation userOp, bytes innerCallRet); + + function executeUserOp(PackedUserOperation calldata userOp, bytes32 /*userOpHash*/) external { + _requireForExecute(); + + // read from the userOp.callData, but skip the "magic" prefix (executeUserOp sig), + // which caused it to call this method. + bytes calldata innerCall = userOp.callData[4 :]; + + bytes memory innerCallRet; + if (innerCall.length > 0) { + (address target, bytes memory data) = abi.decode(innerCall, (address, bytes)); + bool success; + (success, innerCallRet) = target.call(data); + require(success, "inner call failed"); + } + + emit Executed(userOp, innerCallRet); + } +} + +contract TestExecAccountFactory { + TestExecAccount public immutable accountImplementation; + + constructor(IEntryPoint _entryPoint) { + accountImplementation = new TestExecAccount(_entryPoint); + } + + function createAccount(address owner, uint256 salt) public returns (address ret) { + address addr = getAddress(owner, salt); + uint256 codeSize = addr.code.length; + if (codeSize > 0) { + return addr; + } + ret = address(new ERC1967Proxy{salt: bytes32(salt)}( + address(accountImplementation), + abi.encodeCall(SimpleAccount.initialize, (owner)) + )); + } + + /** + * calculate the counterfactual address of this account as it would be returned by createAccount() + */ + function getAddress(address owner, uint256 salt) public view returns (address) { + return Create2.computeAddress(bytes32(salt), keccak256(abi.encodePacked( + type(ERC1967Proxy).creationCode, + abi.encode( + address(accountImplementation), + abi.encodeCall(SimpleAccount.initialize, (owner)) + ) + ))); + } +} diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestExpirePaymaster.sol b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestExpirePaymaster.sol new file mode 100644 index 00000000..103a0b55 --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestExpirePaymaster.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.28; + +import "../core/BasePaymaster.sol"; +import "../core/UserOperationLib.sol"; +import "../core/Helpers.sol"; + +/** + * test expiry mechanism: paymasterData encodes the "validUntil" and validAfter" times + */ +contract TestExpirePaymaster is BasePaymaster { + // solhint-disable no-empty-blocks + constructor(IEntryPoint _entryPoint) BasePaymaster(_entryPoint) + {} + + function _validatePaymasterUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash, uint256 maxCost) + internal virtual override view + returns (bytes memory context, uint256 validationData) { + (userOp, userOpHash, maxCost); + (uint48 validAfter, uint48 validUntil) = abi.decode(userOp.paymasterAndData[PAYMASTER_DATA_OFFSET :], (uint48, uint48)); + validationData = _packValidationData(false, validUntil, validAfter); + context = ""; + } +} diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestExpiryAccount.sol b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestExpiryAccount.sol new file mode 100644 index 00000000..53c849ea --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestExpiryAccount.sol @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.28; + +import "../accounts/SimpleAccount.sol"; +import "../core/Helpers.sol"; + +/** + * A test account, for testing expiry. + * add "temporary" owners, each with a time range (since..till) times for each. + * NOTE: this is not a full "session key" implementation: a real session key should probably limit + * other things, like target contracts and methods to be called. + * also, the "since" value is not really useful, only for testing the entrypoint. + */ +contract TestExpiryAccount is SimpleAccount { + + mapping(address => uint48) public ownerAfter; + mapping(address => uint48) public ownerUntil; + + // solhint-disable-next-line no-empty-blocks + constructor(IEntryPoint anEntryPoint) SimpleAccount(anEntryPoint) {} + + function initialize(address anOwner) public virtual override initializer { + super._initialize(anOwner); + addTemporaryOwner(anOwner, 0, type(uint48).max); + } + + // As this is a test contract, no need for proxy, so no need to disable init + // solhint-disable-next-line no-empty-blocks + function _disableInitializers() internal override {} + + function addTemporaryOwner(address owner, uint48 _after, uint48 _until) public onlyOwner { + require(_until > _after, "wrong until/after"); + ownerAfter[owner] = _after; + ownerUntil[owner] = _until; + } + + /// implement template method of BaseAccount + function _validateSignature(PackedUserOperation calldata userOp, bytes32 userOpHash) + internal override view returns (uint256 validationData) { + address signer = ECDSA.recover(userOpHash,userOp.signature); + uint48 _until = ownerUntil[signer]; + uint48 _after = ownerAfter[signer]; + + // We have "until" value for all valid owners. so zero means "invalid signature" + bool sigFailed = _until == 0; + return _packValidationData(sigFailed, _until, _after); + } +} diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestHelpers.sol b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestHelpers.sol new file mode 100644 index 00000000..fea431f2 --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestHelpers.sol @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.28; + +import "../core/Helpers.sol"; + +contract TestHelpers { + + function parseValidationData(uint256 validationData) public pure returns (ValidationData memory) { + return _parseValidationData(validationData); + } + + function packValidationDataStruct(ValidationData memory data) public pure returns (uint256) { + return _packValidationData(data); + } + + function packValidationData(bool sigFailed, uint48 validUntil, uint48 validAfter) public pure returns (uint256) { + return _packValidationData(sigFailed, validUntil, validAfter); + } +} diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestPaymasterAcceptAll.sol b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestPaymasterAcceptAll.sol new file mode 100644 index 00000000..6a388ab8 --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestPaymasterAcceptAll.sol @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.28; + +import "../core/BasePaymaster.sol"; +import "../core/Helpers.sol"; + +/** + * test paymaster, that pays for everything, without any check. + */ +contract TestPaymasterAcceptAll is BasePaymaster { + + constructor(IEntryPoint _entryPoint) BasePaymaster(_entryPoint) { + // to support "deterministic address" factory + // solhint-disable avoid-tx-origin + if (tx.origin != msg.sender) { + _transferOwnership(tx.origin); + } + + } + + function _validatePaymasterUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash, uint256 maxCost) + internal virtual override view + returns (bytes memory context, uint256 validationData) { + (userOp, userOpHash, maxCost); + return ("", SIG_VALIDATION_SUCCESS); + } +} diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestPaymasterRevertCustomError.sol b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestPaymasterRevertCustomError.sol new file mode 100644 index 00000000..8a7171e3 --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestPaymasterRevertCustomError.sol @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.28; + +import "../core/BasePaymaster.sol"; + +/** + * test postOp revert with custom error + */ +error CustomError(string customReason); + +contract TestPaymasterRevertCustomError is BasePaymaster { + bytes32 private constant INNER_OUT_OF_GAS = hex"deaddead"; + + enum RevertType { + customError, + entryPointError + } + + RevertType private revertType; + + // solhint-disable no-empty-blocks + constructor(IEntryPoint _entryPoint) BasePaymaster(_entryPoint) + {} + + function _validatePaymasterUserOp(PackedUserOperation calldata userOp, bytes32, uint256) + internal virtual override view + returns (bytes memory context, uint256 validationData) { + validationData = 0; + context = abi.encodePacked(userOp.sender); + } + + function setRevertType(RevertType _revertType) external { + revertType = _revertType; + } + + function _postOp(PostOpMode, bytes calldata, uint256, uint256) internal view override { + if (revertType == RevertType.customError){ + revert CustomError("this is a long revert reason string we are looking for"); + } + else if (revertType == RevertType.entryPointError){ + // solhint-disable-next-line no-inline-assembly + assembly { + mstore(0, INNER_OUT_OF_GAS) + revert(0, 32) + } + } + } +} diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestPaymasterWithPostOp.sol b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestPaymasterWithPostOp.sol new file mode 100644 index 00000000..a7a513d8 --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestPaymasterWithPostOp.sol @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.28; + +import "./TestPaymasterAcceptAll.sol"; +/* solhint-disable no-empty-blocks */ + +/** + * test paymaster, that pays for everything, without any check. + * explicitly returns a context, to test cost (for entrypoint) to call postOp + */ +contract TestPaymasterWithPostOp is TestPaymasterAcceptAll { + event PostOpActualGasCost(uint256 actualGasCost, bytes context, bool isSame); + + bytes public theContext; + + constructor(IEntryPoint _entryPoint) TestPaymasterAcceptAll(_entryPoint) { + setContext("1"); + } + + function setContext(bytes memory _context) public { + theContext = _context; + } + + function _validatePaymasterUserOp(PackedUserOperation calldata, bytes32, uint256) + internal virtual override view + returns (bytes memory context, uint256 validationData) { + // return a context, to force a call for postOp. + return (theContext, SIG_VALIDATION_SUCCESS); + } + + function _postOp(PostOpMode, bytes calldata context, uint256 actualGasCost, uint256) + internal override { + bool isSame = keccak256(context) == keccak256(theContext); + emit PostOpActualGasCost(actualGasCost, context, isSame); + + } +} diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestRevertAccount.sol b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestRevertAccount.sol new file mode 100644 index 00000000..8648e221 --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestRevertAccount.sol @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.28; +/* solhint-disable no-inline-assembly */ + +import "../accounts/SimpleAccount.sol"; +contract TestRevertAccount is IAccount { + IEntryPoint private ep; + constructor(IEntryPoint _ep) payable { + ep = _ep; + } + + function validateUserOp(PackedUserOperation calldata, bytes32, uint256 missingAccountFunds) + external override returns (uint256 validationData) { + ep.depositTo{value : missingAccountFunds}(address(this)); + return SIG_VALIDATION_SUCCESS; + } + + function revertLong(uint256 length) public pure{ + assembly { + revert(0, length) + } + } +} diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestSignatureAggregator.sol b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestSignatureAggregator.sol new file mode 100644 index 00000000..0b913466 --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestSignatureAggregator.sol @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.28; + +/* solhint-disable reason-string */ + +import "../interfaces/IAggregator.sol"; +import "../interfaces/IEntryPoint.sol"; +import "../accounts/SimpleAccount.sol"; + +/** + * test signature aggregator. + * the aggregated signature is the SUM of the nonce fields.. + */ +contract TestSignatureAggregator is IAggregator { + + /// @inheritdoc IAggregator + function validateSignatures(PackedUserOperation[] calldata userOps, bytes calldata signature) external pure override { + uint256 sum = 0; + for (uint256 i = 0; i < userOps.length; i++) { + uint256 nonce = userOps[i].nonce; + sum += nonce; + } + require(signature.length == 32, "TestSignatureValidator: sig must be uint256"); + (uint256 sig) = abi.decode(signature, (uint256)); + require(sig == sum, "TestSignatureValidator: aggregated signature mismatch (nonce sum)"); + } + + /// @inheritdoc IAggregator + function validateUserOpSignature(PackedUserOperation calldata) + external pure returns (bytes memory) { + return ""; + } + + /** + * dummy test aggregator: sum all nonce values of UserOps. + */ + function aggregateSignatures(PackedUserOperation[] calldata userOps) external pure returns (bytes memory aggregatedSignature) { + uint256 sum = 0; + for (uint256 i = 0; i < userOps.length; i++) { + sum += userOps[i].nonce; + } + return abi.encode(sum); + } + + /** + * Calls the 'addStake' method of the EntryPoint. Forwards the entire msg.value to this call. + * @param entryPoint - the EntryPoint to send the stake to. + * @param delay - the new lock duration before the deposit can be withdrawn. + */ + function addStake(IEntryPoint entryPoint, uint32 delay) external payable { + entryPoint.addStake{value: msg.value}(delay); + } +} diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestToken.sol b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestToken.sol new file mode 100644 index 00000000..0f616e4c --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestToken.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.28; + +import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; + +contract TestToken is ERC20 { + constructor () + // solhint-disable-next-line no-empty-blocks + ERC20("TST", "TestToken") { + } + + function mint(address sender, uint256 amount) external { + _mint(sender, amount); + } +} diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestUniswap.sol b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestUniswap.sol new file mode 100644 index 00000000..1bae6140 --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestUniswap.sol @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.28; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol"; + +import "./TestWrappedNativeToken.sol"; + +/// @notice Very basic simulation of what Uniswap does with the swaps for the unit tests on the TokenPaymaster +/// @dev Do not use to test any actual Uniswap interaction logic as this is way too simplistic +contract TestUniswap { + TestWrappedNativeToken public weth; + + constructor(TestWrappedNativeToken _weth){ + weth = _weth; + } + + event StubUniswapExchangeEvent(uint256 amountIn, uint256 amountOut, address tokenIn, address tokenOut); + + function exactOutputSingle(ISwapRouter.ExactOutputSingleParams calldata params) external returns (uint256) { + uint256 amountIn = params.amountInMaximum - 5; + emit StubUniswapExchangeEvent( + amountIn, + params.amountOut, + params.tokenIn, + params.tokenOut + ); + IERC20(params.tokenIn).transferFrom(msg.sender, address(this), amountIn); + IERC20(params.tokenOut).transfer(params.recipient, params.amountOut); + return amountIn; + } + + function exactInputSingle(ISwapRouter.ExactInputSingleParams calldata params) external returns (uint256) { + uint256 amountOut = params.amountOutMinimum + 5; + emit StubUniswapExchangeEvent( + params.amountIn, + amountOut, + params.tokenIn, + params.tokenOut + ); + IERC20(params.tokenIn).transferFrom(msg.sender, address(this), params.amountIn); + IERC20(params.tokenOut).transfer(params.recipient, amountOut); + return amountOut; + } + + /// @notice Simplified code copied from here: + /// https://github.com/Uniswap/v3-periphery/blob/main/contracts/base/PeripheryPayments.sol#L19 + function unwrapWETH9(uint256 amountMinimum, address recipient) public payable { + uint256 balanceWETH9 = weth.balanceOf(address(this)); + require(balanceWETH9 >= amountMinimum, "Insufficient WETH9"); + + if (balanceWETH9 > 0) { + weth.withdraw(balanceWETH9); + payable(recipient).transfer(balanceWETH9); + } + } + + // solhint-disable-next-line no-empty-blocks + receive() external payable {} +} diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestUtil.sol b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestUtil.sol new file mode 100644 index 00000000..9538b2d5 --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestUtil.sol @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.28; + +import "../interfaces/PackedUserOperation.sol"; +import "../core/Eip7702Support.sol"; + +contract TestUtil { + using UserOperationLib for PackedUserOperation; + + function encodeUserOp(PackedUserOperation calldata op) external pure returns (bytes memory){ + return op.encode(0); + } + + function isEip7702InitCode(bytes calldata initCode) external pure returns (bool) { + return Eip7702Support._isEip7702InitCode(initCode); + } +} diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestWarmColdAccount.sol b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestWarmColdAccount.sol new file mode 100644 index 00000000..9201d711 --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestWarmColdAccount.sol @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.28; +/* solhint-disable no-inline-assembly */ + +import "../interfaces/IEntryPoint.sol"; +import "../interfaces/IAccount.sol"; +import "../core/Helpers.sol"; + +// Using eip-2929 (https://eips.ethereum.org/EIPS/eip-2929) warm/cold storage access gas costs to detect simulation vs execution +// COLD_ACCOUNT_ACCESS_COST == 2600, COLD_SLOAD_COST == 2100, WARM_STORAGE_READ_COST == 100 +contract TestWarmColdAccount is IAccount { + IEntryPoint private ep; + uint256 public state = 1; + constructor(IEntryPoint _ep) payable { + ep = _ep; + } + + function validateUserOp(PackedUserOperation calldata userOp, bytes32, uint256 missingAccountFunds) + external override returns (uint256 validationData) { + ep.depositTo{value : missingAccountFunds}(address(this)); + if (userOp.nonce == 1) { + // can only succeed if storage is already warm + this.touchStorage{gas: 1000}(); + } else if (userOp.nonce == 2) { + address paymaster = address(bytes20(userOp.paymasterAndData[: 20])); + // can only succeed if storage is already warm + this.touchPaymaster{gas: 1000}(paymaster); + } + return SIG_VALIDATION_SUCCESS; + } + + function touchStorage() public view returns (uint256) { + return state; + } + + function touchPaymaster(address paymaster) public view returns (uint256) { + return paymaster.code.length; + } +} diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestWrappedNativeToken.sol b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestWrappedNativeToken.sol new file mode 100644 index 00000000..3070525c --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/test/TestWrappedNativeToken.sol @@ -0,0 +1,29 @@ +// SPDX-License-Identifier:GPL-3.0 +pragma solidity ^0.8.28; + +import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; + +/** + * @notice The minimal "Wrapped Ether" ERC-20 token implementation. + */ +contract TestWrappedNativeToken is ERC20 { + + // solhint-disable-next-line no-empty-blocks + constructor() ERC20("Wrapped Native Token", "wnTok") { + } + + receive() external payable { + deposit(); + } + + function deposit() public payable { + _mint(msg.sender, msg.value); + } + + function withdraw(uint256 amount) public { + _burn(msg.sender, amount); + // solhint-disable-next-line avoid-low-level-calls + (bool success,) = msg.sender.call{value:amount}(""); + require(success, "transfer failed"); + } +} diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/utils/Exec.sol b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/utils/Exec.sol new file mode 100644 index 00000000..ef06f9db --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/contracts/utils/Exec.sol @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.28; + +// solhint-disable no-inline-assembly + +/** + * Utility functions helpful when making different kinds of contract calls in Solidity. + */ +library Exec { + + function call( + address to, + uint256 value, + bytes memory data, + uint256 txGas + ) internal returns (bool success) { + assembly ("memory-safe") { + success := call(txGas, to, value, add(data, 0x20), mload(data), 0, 0) + } + } + + function staticcall( + address to, + bytes memory data, + uint256 txGas + ) internal view returns (bool success) { + assembly ("memory-safe") { + success := staticcall(txGas, to, add(data, 0x20), mload(data), 0, 0) + } + } + + function delegateCall( + address to, + bytes memory data, + uint256 txGas + ) internal returns (bool success) { + assembly ("memory-safe") { + success := delegatecall(txGas, to, add(data, 0x20), mload(data), 0, 0) + } + } + + // get returned data from last call or delegateCall + // maxLen - maximum length of data to return, or zero, for the full length + function getReturnData(uint256 maxLen) internal pure returns (bytes memory returnData) { + assembly ("memory-safe") { + let len := returndatasize() + if gt(maxLen,0) { + if gt(len, maxLen) { + len := maxLen + } + } + let ptr := mload(0x40) + mstore(0x40, add(ptr, add(len, 0x20))) + mstore(ptr, len) + returndatacopy(add(ptr, 0x20), 0, len) + returnData := ptr + } + } + + // revert with explicit byte array (probably reverted info from call) + function revertWithData(bytes memory returnData) internal pure { + assembly ("memory-safe") { + revert(add(returnData, 32), mload(returnData)) + } + } + + // Propagate revert data from last call + function revertWithReturnData() internal pure { + revertWithData(getReturnData(0)); + } +} diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/deploy/1_deploy_entrypoint.ts b/dependencies/eth-infinitism-account-abstraction-0.8.0/deploy/1_deploy_entrypoint.ts new file mode 100644 index 00000000..f714da04 --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/deploy/1_deploy_entrypoint.ts @@ -0,0 +1,20 @@ +import { HardhatRuntimeEnvironment } from 'hardhat/types' +import { DeployFunction } from 'hardhat-deploy/types' +import { ethers } from 'hardhat' + +const deployEntryPoint: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const provider = ethers.provider + const from = await provider.getSigner().getAddress() + + const ret = await hre.deployments.deploy( + 'EntryPoint', { + from, + args: [], + gasLimit: 6e6, + deterministicDeployment: process.env.SALT ?? true, + log: true + }) + console.log('==entrypoint addr=', ret.address) +} + +export default deployEntryPoint diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/deploy/2_deploy_SimpleAccountFactory.ts b/dependencies/eth-infinitism-account-abstraction-0.8.0/deploy/2_deploy_SimpleAccountFactory.ts new file mode 100644 index 00000000..ca8ce0d2 --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/deploy/2_deploy_SimpleAccountFactory.ts @@ -0,0 +1,34 @@ +import { HardhatRuntimeEnvironment } from 'hardhat/types' +import { DeployFunction } from 'hardhat-deploy/types' +import { ethers } from 'hardhat' + +const deploySimpleAccountFactory: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const provider = ethers.provider + const from = await provider.getSigner().getAddress() + const network = await provider.getNetwork() + // only deploy on local test network. + + const forceDeployFactory = process.argv.join(' ').match(/simple-account-factory/) != null + + if (!forceDeployFactory && network.chainId !== 31337 && network.chainId !== 1337) { + return + } + + const entrypoint = await hre.deployments.get('EntryPoint') + await hre.deployments.deploy( + 'SimpleAccountFactory', { + from, + args: [entrypoint.address], + gasLimit: 6e6, + log: true, + deterministicDeployment: true + }) + + await hre.deployments.deploy('TestCounter', { + from, + deterministicDeployment: true, + log: true + }) +} + +export default deploySimpleAccountFactory diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/deployments/ethereum/.chainId b/dependencies/eth-infinitism-account-abstraction-0.8.0/deployments/ethereum/.chainId new file mode 100644 index 00000000..56a6051c --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/deployments/ethereum/.chainId @@ -0,0 +1 @@ +1 \ No newline at end of file diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/deployments/ethereum/EntryPoint.json b/dependencies/eth-infinitism-account-abstraction-0.8.0/deployments/ethereum/EntryPoint.json new file mode 100644 index 00000000..8a1309de --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/deployments/ethereum/EntryPoint.json @@ -0,0 +1,1090 @@ +{ + "address": "0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "ret", + "type": "bytes" + } + ], + "name": "DelegateAndRevert", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "opIndex", + "type": "uint256" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "FailedOp", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "opIndex", + "type": "uint256" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "internalType": "bytes", + "name": "inner", + "type": "bytes" + } + ], + "name": "FailedOpWithRevert", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidShortString", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "returnData", + "type": "bytes" + } + ], + "name": "PostOpReverted", + "type": "error" + }, + { + "inputs": [], + "name": "ReentrancyGuardReentrantCall", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "SenderAddressResult", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "aggregator", + "type": "address" + } + ], + "name": "SignatureValidationFailed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "str", + "type": "string" + } + ], + "name": "StringTooLong", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "userOpHash", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "factory", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "paymaster", + "type": "address" + } + ], + "name": "AccountDeployed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "BeforeExecution", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalDeposit", + "type": "uint256" + } + ], + "name": "Deposited", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "EIP712DomainChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "userOpHash", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "revertReason", + "type": "bytes" + } + ], + "name": "PostOpRevertReason", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "aggregator", + "type": "address" + } + ], + "name": "SignatureAggregatorChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalStaked", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "unstakeDelaySec", + "type": "uint256" + } + ], + "name": "StakeLocked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "withdrawTime", + "type": "uint256" + } + ], + "name": "StakeUnlocked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "withdrawAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "StakeWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "userOpHash", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "paymaster", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "actualGasCost", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "actualGasUsed", + "type": "uint256" + } + ], + "name": "UserOperationEvent", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "userOpHash", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + } + ], + "name": "UserOperationPrefundTooLow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "userOpHash", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "revertReason", + "type": "bytes" + } + ], + "name": "UserOperationRevertReason", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "withdrawAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Withdrawn", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "unstakeDelaySec", + "type": "uint32" + } + ], + "name": "addStake", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "delegateAndRevert", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "depositTo", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "eip712Domain", + "outputs": [ + { + "internalType": "bytes1", + "name": "fields", + "type": "bytes1" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "version", + "type": "string" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "verifyingContract", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + }, + { + "internalType": "uint256[]", + "name": "extensions", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getDepositInfo", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "deposit", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "staked", + "type": "bool" + }, + { + "internalType": "uint112", + "name": "stake", + "type": "uint112" + }, + { + "internalType": "uint32", + "name": "unstakeDelaySec", + "type": "uint32" + }, + { + "internalType": "uint48", + "name": "withdrawTime", + "type": "uint48" + } + ], + "internalType": "struct IStakeManager.DepositInfo", + "name": "info", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getDomainSeparatorV4", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint192", + "name": "key", + "type": "uint192" + } + ], + "name": "getNonce", + "outputs": [ + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getPackedUserOpTypeHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "initCode", + "type": "bytes" + } + ], + "name": "getSenderAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "initCode", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "callData", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "accountGasLimits", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "preVerificationGas", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "gasFees", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "paymasterAndData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "internalType": "struct PackedUserOperation", + "name": "userOp", + "type": "tuple" + } + ], + "name": "getUserOpHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "components": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "initCode", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "callData", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "accountGasLimits", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "preVerificationGas", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "gasFees", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "paymasterAndData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "internalType": "struct PackedUserOperation[]", + "name": "userOps", + "type": "tuple[]" + }, + { + "internalType": "contract IAggregator", + "name": "aggregator", + "type": "address" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "internalType": "struct IEntryPoint.UserOpsPerAggregator[]", + "name": "opsPerAggregator", + "type": "tuple[]" + }, + { + "internalType": "address payable", + "name": "beneficiary", + "type": "address" + } + ], + "name": "handleAggregatedOps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "initCode", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "callData", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "accountGasLimits", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "preVerificationGas", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "gasFees", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "paymasterAndData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "internalType": "struct PackedUserOperation[]", + "name": "ops", + "type": "tuple[]" + }, + { + "internalType": "address payable", + "name": "beneficiary", + "type": "address" + } + ], + "name": "handleOps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint192", + "name": "key", + "type": "uint192" + } + ], + "name": "incrementNonce", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "callData", + "type": "bytes" + }, + { + "components": [ + { + "components": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "verificationGasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "callGasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "paymasterVerificationGasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "paymasterPostOpGasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "preVerificationGas", + "type": "uint256" + }, + { + "internalType": "address", + "name": "paymaster", + "type": "address" + }, + { + "internalType": "uint256", + "name": "maxFeePerGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxPriorityFeePerGas", + "type": "uint256" + } + ], + "internalType": "struct EntryPoint.MemoryUserOp", + "name": "mUserOp", + "type": "tuple" + }, + { + "internalType": "bytes32", + "name": "userOpHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "prefund", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "contextOffset", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "preOpGas", + "type": "uint256" + } + ], + "internalType": "struct EntryPoint.UserOpInfo", + "name": "opInfo", + "type": "tuple" + }, + { + "internalType": "bytes", + "name": "context", + "type": "bytes" + } + ], + "name": "innerHandleOp", + "outputs": [ + { + "internalType": "uint256", + "name": "actualGasCost", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint192", + "name": "", + "type": "uint192" + } + ], + "name": "nonceSequenceNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "senderCreator", + "outputs": [ + { + "internalType": "contract ISenderCreator", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "unlockStake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "withdrawAddress", + "type": "address" + } + ], + "name": "withdrawStake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "withdrawAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "withdrawAmount", + "type": "uint256" + } + ], + "name": "withdrawTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0xae4eafd1fd17e03b5200f6e2ecad4f669b41d9ba3a4fa0018e92cde985b33129", + "receipt": { + "to": "0x4e59b44847b379578588920ca78fbf26c0b4956c", + "from": "0x81ead4918134ae386dbd04346216e20ab8f822c4", + "contractAddress": null, + "transactionIndex": "73", + "gasUsed": "5034766", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x22a2e4a2ca7737f78438266b72f1ac1090cf176efc925b030de9bc6ff2eafa53", + "transactionHash": "0xae4eafd1fd17e03b5200f6e2ecad4f669b41d9ba3a4fa0018e92cde985b33129", + "logs": [], + "blockNumber": "22075665", + "cumulativeGasUsed": "18957475", + "status": "1" + }, + "args": [], + "numDeployments": 1, + "solcInputHash": "594e0595d5f1f4861d3b32a5f38cc32f", + "metadata": "{\"compiler\":{\"version\":\"0.8.28+commit.7893614a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"ret\",\"type\":\"bytes\"}],\"name\":\"DelegateAndRevert\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"opIndex\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"}],\"name\":\"FailedOp\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"opIndex\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"inner\",\"type\":\"bytes\"}],\"name\":\"FailedOpWithRevert\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidShortString\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"name\":\"PostOpReverted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrancyGuardReentrantCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderAddressResult\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"aggregator\",\"type\":\"address\"}],\"name\":\"SignatureValidationFailed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"str\",\"type\":\"string\"}],\"name\":\"StringTooLong\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"factory\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"paymaster\",\"type\":\"address\"}],\"name\":\"AccountDeployed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"BeforeExecution\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"totalDeposit\",\"type\":\"uint256\"}],\"name\":\"Deposited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"EIP712DomainChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"revertReason\",\"type\":\"bytes\"}],\"name\":\"PostOpRevertReason\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"aggregator\",\"type\":\"address\"}],\"name\":\"SignatureAggregatorChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"totalStaked\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"name\":\"StakeLocked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"withdrawTime\",\"type\":\"uint256\"}],\"name\":\"StakeUnlocked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"withdrawAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"StakeWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"paymaster\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"actualGasCost\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"actualGasUsed\",\"type\":\"uint256\"}],\"name\":\"UserOperationEvent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"}],\"name\":\"UserOperationPrefundTooLow\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"revertReason\",\"type\":\"bytes\"}],\"name\":\"UserOperationRevertReason\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"withdrawAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Withdrawn\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"unstakeDelaySec\",\"type\":\"uint32\"}],\"name\":\"addStake\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"delegateAndRevert\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"depositTo\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"eip712Domain\",\"outputs\":[{\"internalType\":\"bytes1\",\"name\":\"fields\",\"type\":\"bytes1\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"version\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"verifyingContract\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"},{\"internalType\":\"uint256[]\",\"name\":\"extensions\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getDepositInfo\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"deposit\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"staked\",\"type\":\"bool\"},{\"internalType\":\"uint112\",\"name\":\"stake\",\"type\":\"uint112\"},{\"internalType\":\"uint32\",\"name\":\"unstakeDelaySec\",\"type\":\"uint32\"},{\"internalType\":\"uint48\",\"name\":\"withdrawTime\",\"type\":\"uint48\"}],\"internalType\":\"struct IStakeManager.DepositInfo\",\"name\":\"info\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDomainSeparatorV4\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint192\",\"name\":\"key\",\"type\":\"uint192\"}],\"name\":\"getNonce\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getPackedUserOpTypeHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"}],\"name\":\"getSenderAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"bytes32\",\"name\":\"accountGasLimits\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"gasFees\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct PackedUserOperation\",\"name\":\"userOp\",\"type\":\"tuple\"}],\"name\":\"getUserOpHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"bytes32\",\"name\":\"accountGasLimits\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"gasFees\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct PackedUserOperation[]\",\"name\":\"userOps\",\"type\":\"tuple[]\"},{\"internalType\":\"contract IAggregator\",\"name\":\"aggregator\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct IEntryPoint.UserOpsPerAggregator[]\",\"name\":\"opsPerAggregator\",\"type\":\"tuple[]\"},{\"internalType\":\"address payable\",\"name\":\"beneficiary\",\"type\":\"address\"}],\"name\":\"handleAggregatedOps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"bytes32\",\"name\":\"accountGasLimits\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"gasFees\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct PackedUserOperation[]\",\"name\":\"ops\",\"type\":\"tuple[]\"},{\"internalType\":\"address payable\",\"name\":\"beneficiary\",\"type\":\"address\"}],\"name\":\"handleOps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint192\",\"name\":\"key\",\"type\":\"uint192\"}],\"name\":\"incrementNonce\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"paymasterVerificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"paymasterPostOpGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"paymaster\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"}],\"internalType\":\"struct EntryPoint.MemoryUserOp\",\"name\":\"mUserOp\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"prefund\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"contextOffset\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preOpGas\",\"type\":\"uint256\"}],\"internalType\":\"struct EntryPoint.UserOpInfo\",\"name\":\"opInfo\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"context\",\"type\":\"bytes\"}],\"name\":\"innerHandleOp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"actualGasCost\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint192\",\"name\":\"\",\"type\":\"uint192\"}],\"name\":\"nonceSequenceNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"senderCreator\",\"outputs\":[{\"internalType\":\"contract ISenderCreator\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unlockStake\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"withdrawAddress\",\"type\":\"address\"}],\"name\":\"withdrawStake\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"withdrawAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"withdrawAmount\",\"type\":\"uint256\"}],\"name\":\"withdrawTo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"custom:security-contact\":\"https://bounty.ethereum.org\",\"errors\":{\"FailedOp(uint256,string)\":[{\"params\":{\"opIndex\":\"- Index into the array of ops to the failed one (in simulateValidation, this is always zero).\",\"reason\":\"- Revert reason. The string starts with a unique code \\\"AAmn\\\", where \\\"m\\\" is \\\"1\\\" for factory, \\\"2\\\" for account and \\\"3\\\" for paymaster issues, so a failure can be attributed to the correct entity.\"}}],\"FailedOpWithRevert(uint256,string,bytes)\":[{\"details\":\"note that inner is truncated to 2048 bytes\",\"params\":{\"inner\":\"- data from inner cought revert reason\",\"opIndex\":\"- Index into the array of ops to the failed one (in simulateValidation, this is always zero).\",\"reason\":\"- Revert reason. see FailedOp(uint256,string), above\"}}],\"ReentrancyGuardReentrantCall()\":[{\"details\":\"Unauthorized reentrant call.\"}],\"SignatureValidationFailed(address)\":[{\"params\":{\"aggregator\":\"The aggregator that failed to verify the signature\"}}]},\"events\":{\"AccountDeployed(bytes32,address,address,address)\":{\"params\":{\"factory\":\"- The factory used to deploy this account (in the initCode)\",\"paymaster\":\"- The paymaster used by this UserOp\",\"sender\":\"- The account that is deployed\",\"userOpHash\":\"- The userOp that deployed this account. UserOperationEvent will follow.\"}},\"EIP712DomainChanged()\":{\"details\":\"MAY be emitted to signal that the domain could have changed.\"},\"PostOpRevertReason(bytes32,address,uint256,bytes)\":{\"params\":{\"nonce\":\"- The nonce used in the request.\",\"revertReason\":\"- The return bytes from the reverted call to \\\"postOp\\\".\",\"sender\":\"- The sender of this request.\",\"userOpHash\":\"- The request unique identifier.\"}},\"SignatureAggregatorChanged(address)\":{\"params\":{\"aggregator\":\"- The aggregator used for the following UserOperationEvents.\"}},\"UserOperationPrefundTooLow(bytes32,address,uint256)\":{\"params\":{\"nonce\":\"- The nonce used in the request.\",\"sender\":\"- The sender of this request.\",\"userOpHash\":\"- The request unique identifier.\"}},\"UserOperationRevertReason(bytes32,address,uint256,bytes)\":{\"params\":{\"nonce\":\"- The nonce used in the request.\",\"revertReason\":\"- The return bytes from the reverted \\\"callData\\\" call.\",\"sender\":\"- The sender of this request.\",\"userOpHash\":\"- The request unique identifier.\"}}},\"kind\":\"dev\",\"methods\":{\"addStake(uint32)\":{\"params\":{\"unstakeDelaySec\":\"- The new lock duration before the deposit can be withdrawn.\"}},\"balanceOf(address)\":{\"params\":{\"account\":\"- The account to query.\"},\"returns\":{\"_0\":\"- The deposit (for gas payment) of the account.\"}},\"delegateAndRevert(address,bytes)\":{\"details\":\"calling this method, the EntryPoint will make a delegatecall to the given data, and report (via revert) the result. The method always revert, so is only useful off-chain for dry run calls, in cases where state-override to replace actual EntryPoint code is less convenient.\",\"params\":{\"data\":\"data to pass to target in a delegatecall\",\"target\":\"a target contract to make a delegatecall from entrypoint\"}},\"depositTo(address)\":{\"params\":{\"account\":\"- The account to add to.\"}},\"eip712Domain()\":{\"details\":\"See {IERC-5267}.\"},\"getDepositInfo(address)\":{\"params\":{\"account\":\"- The account to query.\"},\"returns\":{\"info\":\" - Full deposit information of given account.\"}},\"getNonce(address,uint192)\":{\"params\":{\"key\":\"the high 192 bit of the nonce\",\"sender\":\"the account address\"},\"returns\":{\"nonce\":\"a full nonce to pass for next UserOp with this sender.\"}},\"getSenderAddress(bytes)\":{\"params\":{\"initCode\":\"- The constructor code to be passed into the UserOperation.\"}},\"getUserOpHash((address,uint256,bytes,bytes,bytes32,uint256,bytes32,bytes,bytes))\":{\"params\":{\"userOp\":\"- The user operation to generate the request ID for.\"},\"returns\":{\"_0\":\"hash the hash of this UserOperation\"}},\"handleAggregatedOps(((address,uint256,bytes,bytes,bytes32,uint256,bytes32,bytes,bytes)[],address,bytes)[],address)\":{\"params\":{\"beneficiary\":\"- The address to receive the fees.\",\"opsPerAggregator\":\"- The operations to execute, grouped by aggregator (or address(0) for no-aggregator accounts).\"}},\"handleOps((address,uint256,bytes,bytes,bytes32,uint256,bytes32,bytes,bytes)[],address)\":{\"params\":{\"beneficiary\":\"- The address to receive the fees.\",\"ops\":\"- The operations to execute.\"}},\"incrementNonce(uint192)\":{\"params\":{\"key\":\"- the \\\"nonce key\\\" to increment the \\\"nonce sequence\\\" for.\"}},\"innerHandleOp(bytes,((address,uint256,uint256,uint256,uint256,uint256,uint256,address,uint256,uint256),bytes32,uint256,uint256,uint256),bytes)\":{\"params\":{\"callData\":\"- The callData to execute.\",\"context\":\"- The context bytes.\",\"opInfo\":\"- The UserOpInfo struct.\"},\"returns\":{\"actualGasCost\":\"- the actual cost in eth this UserOperation paid for gas\"}},\"supportsInterface(bytes4)\":{\"details\":\"Returns true if this contract implements the interface defined by `interfaceId`. See the corresponding https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section] to learn more about how these ids are created. This function call must use less than 30 000 gas.\"},\"withdrawStake(address)\":{\"params\":{\"withdrawAddress\":\"- The address to send withdrawn value.\"}},\"withdrawTo(address,uint256)\":{\"params\":{\"withdrawAddress\":\"- The address to send withdrawn value.\",\"withdrawAmount\":\"- The amount to withdraw.\"}}},\"version\":1},\"userdoc\":{\"errors\":{\"FailedOp(uint256,string)\":[{\"notice\":\"A custom revert error of handleOps andhandleAggregatedOps, to identify the offending op. Should be caught in off-chain handleOps/handleAggregatedOps simulation and not happen on-chain. Useful for mitigating DoS attempts against batchers or for troubleshooting of factory/account/paymaster reverts. NOTE: If simulateValidation passes successfully, there should be no reason for handleOps to fail on it.\"}],\"FailedOpWithRevert(uint256,string,bytes)\":[{\"notice\":\"A custom revert error of handleOps and handleAggregatedOps, to report a revert by account or paymaster.\"}],\"SignatureValidationFailed(address)\":[{\"notice\":\"Error case when a signature aggregator fails to verify the aggregated signature it had created.\"}]},\"events\":{\"AccountDeployed(bytes32,address,address,address)\":{\"notice\":\"Account \\\"sender\\\" was deployed.\"},\"BeforeExecution()\":{\"notice\":\"An event emitted by handleOps() and handleAggregatedOps(), before starting the execution loop. Any event emitted before this event, is part of the validation.\"},\"PostOpRevertReason(bytes32,address,uint256,bytes)\":{\"notice\":\"An event emitted if the UserOperation Paymaster's \\\"postOp\\\" call reverted with non-zero length.\"},\"SignatureAggregatorChanged(address)\":{\"notice\":\"Signature aggregator used by the following UserOperationEvents within this bundle.\"},\"UserOperationPrefundTooLow(bytes32,address,uint256)\":{\"notice\":\"UserOp consumed more than prefund. The UserOperation is reverted, and no refund is made.\"},\"UserOperationRevertReason(bytes32,address,uint256,bytes)\":{\"notice\":\"An event emitted if the UserOperation \\\"callData\\\" reverted with non-zero length.\"}},\"kind\":\"user\",\"methods\":{\"addStake(uint32)\":{\"notice\":\"Add to the account's stake - amount and delay any pending unstake is first cancelled.\"},\"balanceOf(address)\":{\"notice\":\"Get account balance.\"},\"delegateAndRevert(address,bytes)\":{\"notice\":\"Helper method for dry-run testing.\"},\"depositTo(address)\":{\"notice\":\"Add to the deposit of the given account.\"},\"getDepositInfo(address)\":{\"notice\":\"Get deposit info.\"},\"getNonce(address,uint192)\":{\"notice\":\"Return the next nonce for this sender. Within a given key, the nonce values are sequenced (starting with zero, and incremented by one on each userop) But UserOp with different keys can come with arbitrary order.\"},\"getSenderAddress(bytes)\":{\"notice\":\"Get counterfactual sender address. Calculate the sender contract address that will be generated by the initCode and salt in the UserOperation. This method always revert, and returns the address in SenderAddressResult error.this method cannot be used for EIP-7702 derived contracts.\"},\"getUserOpHash((address,uint256,bytes,bytes,bytes32,uint256,bytes32,bytes,bytes))\":{\"notice\":\"Generate a request Id - unique identifier for this request. The request ID is a hash over the content of the userOp (except the signature), entrypoint address, chainId and (optionally) 7702 delegate address\"},\"handleAggregatedOps(((address,uint256,bytes,bytes,bytes32,uint256,bytes32,bytes,bytes)[],address,bytes)[],address)\":{\"notice\":\"Execute a batch of UserOperation with Aggregators\"},\"handleOps((address,uint256,bytes,bytes,bytes32,uint256,bytes32,bytes,bytes)[],address)\":{\"notice\":\"Execute a batch of UserOperations. No signature aggregator is used. If any account requires an aggregator (that is, it returned an aggregator when performing simulateValidation), then handleAggregatedOps() must be used instead.\"},\"incrementNonce(uint192)\":{\"notice\":\"Manually increment the nonce of the sender. This method is exposed just for completeness.. Account does NOT need to call it, neither during validation, nor elsewhere, as the EntryPoint will update the nonce regardless. Possible use-case is call it with various keys to \\\"initialize\\\" their nonces to one, so that future UserOperations will not pay extra for the first transaction with a given key.\"},\"innerHandleOp(bytes,((address,uint256,uint256,uint256,uint256,uint256,uint256,address,uint256,uint256),bytes32,uint256,uint256,uint256),bytes)\":{\"notice\":\"Inner function to handle a UserOperation. Must be declared \\\"external\\\" to open a call context, but it can only be called by handleOps.\"},\"nonceSequenceNumber(address,uint192)\":{\"notice\":\"The next valid sequence number for a given nonce key.\"},\"senderCreator()\":{\"notice\":\"Retrieves the immutable SenderCreator contract which is responsible for deployment of sender contracts.\"},\"unlockStake()\":{\"notice\":\"Attempt to unlock the stake. The value can be withdrawn (using withdrawStake) after the unstake delay.\"},\"withdrawStake(address)\":{\"notice\":\"Withdraw from the (unlocked) stake. Must first call unlockStake and wait for the unstakeDelay to pass.\"},\"withdrawTo(address,uint256)\":{\"notice\":\"Withdraw from the deposit.\"}},\"notice\":\"Account-Abstraction (EIP-4337) singleton EntryPoint v0.8 implementation. Only one instance required on each chain.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/core/EntryPoint.sol\":\"EntryPoint\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":1000000},\"remappings\":[],\"viaIR\":true},\"sources\":{\"@openzeppelin/contracts/interfaces/IERC5267.sol\":{\"keccak256\":\"0x92aa1df62dc3d33f1656d63bede0923e0df0b706ad4137c8b10b0a8fe549fd92\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c5c0f29195ad64cbe556da8e257dac8f05f78c53f90323c0d2accf8e6922d33a\",\"dweb:/ipfs/QmQ61TED8uaCZwcbh8KkgRSsCav7x7HbcGHwHts3U4DmUP\"]},\"@openzeppelin/contracts/utils/Panic.sol\":{\"keccak256\":\"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c6a5ff4f9fd8649b7ee20800b7fa387d3465bd77cf20c2d1068cd5c98e1ed57a\",\"dweb:/ipfs/QmVSaVJf9FXFhdYEYeCEfjMVHrxDh5qL4CGkxdMWpQCrqG\"]},\"@openzeppelin/contracts/utils/ReentrancyGuardTransient.sol\":{\"keccak256\":\"0x534bf5c25d6003a8ce50b400d20fa460c03169ad7baa90d47a912917c36dfe2b\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://cc0cc39c40ea23d3c46e8517e19ebdd877719d3159fa032f2a91802cdd205c79\",\"dweb:/ipfs/QmSoNh7HTkD4TJcBkBKSGSPMMpLUZKE7s9f2G6mjdaJywg\"]},\"@openzeppelin/contracts/utils/ShortStrings.sol\":{\"keccak256\":\"0x7d94fa0af099a2172eb01f9c8a8a443cbe7e0e43654841563e4e09968efdb549\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://65e38fb76b6add407d4557753ae83dd1268e8261195dbe5c19a580d5ba6e4e9a\",\"dweb:/ipfs/QmTkGSJtaQrqjcyWM4AgemeEmKgtDydKPPVRajsUJRQSrK\"]},\"@openzeppelin/contracts/utils/StorageSlot.sol\":{\"keccak256\":\"0xcf74f855663ce2ae00ed8352666b7935f6cddea2932fdf2c3ecd30a9b1cd0e97\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://9f660b1f351b757dfe01438e59888f31f33ded3afcf5cb5b0d9bf9aa6f320a8b\",\"dweb:/ipfs/QmarDJ5hZEgBtCmmrVzEZWjub9769eD686jmzb2XpSU1cM\"]},\"@openzeppelin/contracts/utils/Strings.sol\":{\"keccak256\":\"0x725209b582291bb83058e3078624b53d15a133f7401c30295e7f3704181d2aed\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://0564ddb19c6d870e27b789d8f985283d815267ad7224883c2d5243c8bacc7dc0\",\"dweb:/ipfs/QmeC953H4sj88ZRFdJNFdmpf7J9SksP1wK4jyMHLo66z49\"]},\"@openzeppelin/contracts/utils/TransientSlot.sol\":{\"keccak256\":\"0x9303ef5a2beb555e52ce56598de205ce07ca8988fc67d073687c06cb8fc973d1\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://8b2e48fb42844c25e6cb38e7cfa1d91dcdc054613fd10f608833dbc677acf889\",\"dweb:/ipfs/QmT4HQxbgpWA3fZnK4dY3eXHNCoyBvpvzNq5k7eSt5mR5t\"]},\"@openzeppelin/contracts/utils/cryptography/EIP712.sol\":{\"keccak256\":\"0x10eb97d047f8d84fe263a02bb4a656ac6674f6679d74532cc37546289e073a9d\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://3e41287d40b0c46982f1083d40d32de2761f009c5c51627fe79a7feb0ab1cf5c\",\"dweb:/ipfs/Qme7dbh6HX3ZvUJdbQAcVqXkmyXyfcLiUZRhhon3cU6K8p\"]},\"@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol\":{\"keccak256\":\"0x4515543bc4c78561f6bea83ecfdfc3dead55bd59858287d682045b11de1ae575\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://60601f91440125727244fffd2ba84da7caafecaae0fd887c7ccfec678e02b61e\",\"dweb:/ipfs/QmZnKPBtVDiQS9Dp8gZ4sa3ZeTrWVfqF7yuUd6Y8hwm1Rs\"]},\"@openzeppelin/contracts/utils/introspection/ERC165.sol\":{\"keccak256\":\"0xddce8e17e3d3f9ed818b4f4c4478a8262aab8b11ed322f1bf5ed705bb4bd97fa\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://8084aa71a4cc7d2980972412a88fe4f114869faea3fefa5436431644eb5c0287\",\"dweb:/ipfs/Qmbqfs5dRdPvHVKY8kTaeyc65NdqXRQwRK7h9s5UJEhD1p\"]},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"keccak256\":\"0x79796192ec90263f21b464d5bc90b777a525971d3de8232be80d9c4f9fb353b8\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://f6fda447a62815e8064f47eff0dd1cf58d9207ad69b5d32280f8d7ed1d1e4621\",\"dweb:/ipfs/QmfDRc7pxfaXB2Dh9np5Uf29Na3pQ7tafRS684wd3GLjVL\"]},\"@openzeppelin/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xa00be322d7db5786750ce0ac7e2f5b633ac30a5ed5fa1ced1e74acfc19acecea\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6c84e822f87cbdc4082533b626667b6928715bb2b1e8e7eb96954cebb9e38c8d\",\"dweb:/ipfs/QmZmy9dgxLTerBAQDuuHqbL6EpgRxddqgv5KmwpXYVbKz1\"]},\"@openzeppelin/contracts/utils/math/SafeCast.sol\":{\"keccak256\":\"0x195533c86d0ef72bcc06456a4f66a9b941f38eb403739b00f21fd7c1abd1ae54\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b1d578337048cad08c1c03041cca5978eff5428aa130c781b271ad9e5566e1f8\",\"dweb:/ipfs/QmPFKL2r9CBsMwmUqqdcFPfHZB2qcs9g1HDrPxzWSxomvy\"]},\"@openzeppelin/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb1970fac7b64e6c09611e6691791e848d5e3fe410fa5899e7df2e0afd77a99e3\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://db5fbb3dddd8b7047465b62575d96231ba8a2774d37fb4737fbf23340fabbb03\",\"dweb:/ipfs/QmVUSvooZKEdEdap619tcJjTLcAuH6QBdZqAzWwnAXZAWJ\"]},\"contracts/core/Eip7702Support.sol\":{\"keccak256\":\"0x8e22fc49f3ec8dadd4ec6f6829485d3d301afced9e73da1012e903d4221d715d\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://85c21152f6f1e1754dbae1b9fa85040d9d282a8badd848765845a71acf3bbd99\",\"dweb:/ipfs/QmdNZSjrtoV4RM6fuKKUQU73AYzALsaBwY2tz2Lxz4mNaS\"]},\"contracts/core/EntryPoint.sol\":{\"keccak256\":\"0xc9ecbfe38573b15fb46f67ffafa0dfaf54ccc37b72679aa8ec8ad3a868e19beb\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://61df92ab84b8fcb0104c86719f1dd881ca10674ca73fc3d8b673f85e62f184b5\",\"dweb:/ipfs/QmVfyWSiXwic43BW8U2zMx8wHRv1CsZhUvM7yR61qB1eDq\"]},\"contracts/core/Helpers.sol\":{\"keccak256\":\"0x42b948af5fa14a96149611595df1186800c7558b2de8762e4b45a7c45c16f65e\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://737a7908131ece48a5df1faaa3d0be79c42792379c27f5615dae6aa14cd68c2f\",\"dweb:/ipfs/QmPAxGMDxuek7XWSUVfZpvYE8bustfsjTDVDK8hmE88e1f\"]},\"contracts/core/NonceManager.sol\":{\"keccak256\":\"0x83fc7ce846063465d394b690c377beba26806e7564c77127d8a91b77ca64597c\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://7ed8c369c25b26518b1c8ca43c6c3dddf7ea07c073f2b92408743f61e655dc01\",\"dweb:/ipfs/QmZuWagAa78Wvi8RKD1J1E48YxxW8SJxB6aKeT3EFz72HE\"]},\"contracts/core/SenderCreator.sol\":{\"keccak256\":\"0x3138a92de18e7e39c45020f0e5e7d16da622c01f3846094f7be05c2aefb098fd\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://6f87883de39461c04a76e672b69c968467c4ec3258d1887ba96c989563a843df\",\"dweb:/ipfs/QmPyuTTqCvoaZekGEmzPHN5j8oEXKV9vLxiSCMSLQA7usy\"]},\"contracts/core/StakeManager.sol\":{\"keccak256\":\"0x98b727e4093595bf57eb09d45a9a181a26fca46591fc58601e8eae894d8f931a\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://99d933ae3257d8aad0d32a60f021e37dd0dcedcd94edab905ec7523f34656ef2\",\"dweb:/ipfs/Qme8P8tZ37cexrxjTgrLoXXgbW1nqH8rQp5SLTW99aFsi5\"]},\"contracts/core/UserOperationLib.sol\":{\"keccak256\":\"0x2d3450fa3906422b6fdbbe7f2a2a9e36d6f3751bfa9cd80af88befd6a5be78c1\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://292a0ef5295d7f2016e99d2c228958f7f6de94f5bd9652d8696af15af0094a99\",\"dweb:/ipfs/QmVg4fhkZbUB7AopGcaVPmTdvChq7W9ga8fjrc3XaJNTM2\"]},\"contracts/interfaces/IAccount.sol\":{\"keccak256\":\"0x1030b464b49ce80da46b5b6c9af357c2d526f308de61391db6a4ec767d33b864\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://671945f8e18e7305797312b5a209506be3c9bd1d9b9b561c1e8863bccfa61319\",\"dweb:/ipfs/QmVanLK5Aenrb7J94doiE1C9oHwo86jvv8NrpDeNHwvnii\"]},\"contracts/interfaces/IAccountExecute.sol\":{\"keccak256\":\"0xc313afc1e1b6823126be317611c3a868dc69eb29df43c658464b7188890c40e0\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://f3c2a7fac3764500a7e57cf4b9a610b14125edc4d87371772ec1b3407e89eced\",\"dweb:/ipfs/Qmc2Au3LvywAB5uaEc8ttuGVRZU4Mrgn1XWyqDa2zxtCHp\"]},\"contracts/interfaces/IAggregator.sol\":{\"keccak256\":\"0xdf580eafa015b81bde436d6a5468cc92b531ada84007cef885e923f6dfc5e8bf\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://99f0060626568619ac94d750eb4c0888d92ca5775a6bd957fef9847843835b77\",\"dweb:/ipfs/QmXJer3D9sTkEj3mmUDqpdqfGpe46Rn9G22nGrfZdP2wAT\"]},\"contracts/interfaces/IEntryPoint.sol\":{\"keccak256\":\"0x3b0423737e810dd886183ed32cfed9b45edd315f5fb3e1076fc19f86791adc64\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c43081efaa2eda581b6249053281bb58cb0c4eeb6bf87efc55d95daaec2fc931\",\"dweb:/ipfs/QmXRN2JnyzWZNeFMHauTnDuc7jhxGY4ZkY37HTtjXKdC87\"]},\"contracts/interfaces/INonceManager.sol\":{\"keccak256\":\"0xee493ae200b8c675bdc0da66f7ac6bb883ecea33672d7d0a95526b9eecdedf87\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://979784a0333ac4ef3cc53ab9323a4b7fa574d929bd511f0eed03d3b0370db22d\",\"dweb:/ipfs/QmeiciN5gs4upM6vfKvrRxWiDBUzMU4uJQRRkJajhim9gX\"]},\"contracts/interfaces/IPaymaster.sol\":{\"keccak256\":\"0x6be37abc0760d60a41124e2e3f46185a0d3df48b32bd73174790981f76fbdae8\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c144ba15a63883c7da41fc0729a46108f7d5487dbac2da0bde00aed67f5a2f00\",\"dweb:/ipfs/Qmdh7MzQmCQLh7wz719xMuG2yvMUkKDVwyN44P7pLofJfS\"]},\"contracts/interfaces/ISenderCreator.sol\":{\"keccak256\":\"0x677f651d733162b80d1af7901e4f36469e362737a8353d1d0cc7bb94489e4ba4\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://d6905a80acd70b444ea230b5b582164cb99aaae518bf72c88f8292df31615570\",\"dweb:/ipfs/QmfTKTPwJYf9pmA3T5PE5cCG8GLLDrLaq3jQqMP3pVRL6w\"]},\"contracts/interfaces/IStakeManager.sol\":{\"keccak256\":\"0xe48e904fcac02295aad07fbfa1c1d449a74bf44c04e432afef6f34d1ef726ae0\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://5882b635ea6f5da9ae411485975888431de571f85d4baf35e3db1a83c1f14b85\",\"dweb:/ipfs/QmVSTX36Byr48y8JBmz1hCTGAAyQdTYegQbsSqdRNuSQYz\"]},\"contracts/interfaces/PackedUserOperation.sol\":{\"keccak256\":\"0xb15188e25e45fe73097e279675b6c0beccbd4133ead2260f8f0c4ba840046800\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://5d14c1edd1e95d37c26e54bb34305e2cc9dedc46eb75ec91caeb777678e8ea79\",\"dweb:/ipfs/QmcCL2syVtV7W3XvYx3si84MPkbEJKqEN8hjFNhAPoDDhK\"]},\"contracts/utils/Exec.sol\":{\"keccak256\":\"0x9c724ee22011193ea7f92d3c3c467ee6aa27139d3ddc225c7f1254d241e6ccdd\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://96cc246fe944a212cbb9ba82065b2d380ec80954fcdb5d8d982b476bd5b72868\",\"dweb:/ipfs/QmZ25eFixEhukbfWGz5TBjsp7YohxUqD5i2rxhaghfvHt8\"]}},\"version\":1}", + "bytecode": "0x6101806040523461019557604051610018604082610199565b600781526020810190664552433433333760c81b82526040519161003d604084610199565b600183526020830191603160f81b8352610056816101bc565b6101205261006384610357565b61014052519020918260e05251902080610100524660a0526040519060208201927f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f8452604083015260608201524660808201523060a082015260a081526100cc60c082610199565b5190206080523060c0526040516104f58082016001600160401b0381118382101761018157829161597a833903905ff0801561017657610160526040516154ea9081610490823960805181613511015260a051816135ce015260c051816134e2015260e051816135600152610100518161358601526101205181611884015261014051816118ad0152610160518181816116ce015281816120a801528181615061015261538c0152f35b6040513d5f823e3d90fd5b634e487b7160e01b5f52604160045260245ffd5b5f80fd5b601f909101601f19168101906001600160401b0382119082101761018157604052565b908151602081105f14610236575090601f8151116101f65760208151910151602082106101e7571790565b5f198260200360031b1b161790565b604460209160405192839163305a27a960e01b83528160048401528051918291826024860152018484015e5f828201840152601f01601f19168101030190fd5b6001600160401b03811161018157600254600181811c9116801561034d575b602082101461033957601f8111610306575b50602092601f82116001146102a557928192935f9261029a575b50508160011b915f199060031b1c19161760025560ff90565b015190505f80610281565b601f1982169360025f52805f20915f5b8681106102ee57508360019596106102d6575b505050811b0160025560ff90565b01515f1960f88460031b161c191690555f80806102c8565b919260206001819286850151815501940192016102b5565b60025f52601f60205f20910160051c810190601f830160051c015b81811061032e5750610267565b5f8155600101610321565b634e487b7160e01b5f52602260045260245ffd5b90607f1690610255565b908151602081105f14610382575090601f8151116101f65760208151910151602082106101e7571790565b6001600160401b03811161018157600354600181811c91168015610485575b602082101461033957601f8111610452575b50602092601f82116001146103f157928192935f926103e6575b50508160011b915f199060031b1c19161760035560ff90565b015190505f806103cd565b601f1982169360035f52805f20915f5b86811061043a5750836001959610610422575b505050811b0160035560ff90565b01515f1960f88460031b161c191690555f8080610414565b91926020600181928685015181550194019201610401565b60035f52601f60205f20910160051c810190601f830160051c015b81811061047a57506103b3565b5f815560010161046d565b90607f16906103a156fe6101606040526004361015610024575b3615610019575f80fd5b610022336131f4565b005b5f610140525f3560e01c806242dc53146125d957806301ffc9a7146124875780630396cb60146120cc57806309ccb8801461205b5780630bd28e3b14611fbf57806313c65a6e14611f84578063154e58dc14611f295780631b2e01b814611e93578063205c287814611cf257806322cdde4c14611c6e57806335567e1a14611bb45780635287ce1214611a9457806370a0823114611a29578063765e827f1461198b57806384b0196e1461184b578063850aaf62146117865780639b249f6914611622578063b760faf9146115e1578063bb9fe6bf146113f2578063c23a5cea1461114f5763dbed18e00361000f5734610ec95761012136612d56565b6101005260e052610130613824565b6101405190815b60e0518110610f2e575061014a8261303a565b61012052610140516080526101405160c0525b60e05160c0511061029b577fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f9726101405161014051a161014051608081905290815b60e05181106101e1576101b48361010051614a19565b610140517f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005d6101405180f35b6102436101f18260e05185613267565b73ffffffffffffffffffffffffffffffffffffffff610212602083016132fb565b167f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d6101405161014051a2806132a7565b9061014051915b80831061025c5750505060010161019e565b909194600190610289610270888587613109565b61027f60805161012051613176565b519060805161437c565b0195816080510160805201919061024a565b6102aa60c05160e05183613267565b73ffffffffffffffffffffffffffffffffffffffff6102d860206102ce84806132a7565b60a05293016132fb565b61014051911691905b60a05181106103055750505060a05160805101608052600160c0510160c05261015d565b610316816080510161012051613176565b516103248260a05185613109565b61014051915a81519273ffffffffffffffffffffffffffffffffffffffff61034b826132fb565b168452602081810135908501526fffffffffffffffffffffffffffffffff6080808301358281166060880152811c604087015260a083013560c0808801919091528301359182166101008701521c6101208501526103ac60e082018261331c565b9081610e15575b5050604051936103c282612ee9565b6020850152846040526040810151946effffffffffffffffffffffffffffff8660c08401511760608401511760808401511760a084015117610100840151176101208401511711610daf5750604081015160608201510160808201510160a08201510160c0820151016101008201510294856040860152845173ffffffffffffffffffffffffffffffffffffffff60e08183511692610475898d61046960408b018b61331c565b92909160805101614fb5565b0151169661014051978015610d7e575b87516040810151905173ffffffffffffffffffffffffffffffffffffffff169061014051506040519a8b8960208d01519260208301937f19822f7c00000000000000000000000000000000000000000000000000000000855260248401926104ec93615460565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081018d5261051c908d612c2d565b61014051908c5190846101405190602095f161014051519a3d602003610d73575b60405215610c80575015610c02575b505073ffffffffffffffffffffffffffffffffffffffff825116602083015190610140515260016020526040610140512077ffffffffffffffffffffffffffffffffffffffffffffffff8260401c165f5260205267ffffffffffffffff60405f20918254926105ba84612e80565b90551603610b99575a840311610b305760e0015160609073ffffffffffffffffffffffffffffffffffffffff16610827575b73ffffffffffffffffffffffffffffffffffffffff949260a0859360809360606106219801520135905a900301910152614f15565b911685036107be576107555761064b73ffffffffffffffffffffffffffffffffffffffff91614f15565b91166106ec5761065d576001016102e1565b60a490604051907f220266b600000000000000000000000000000000000000000000000000000000825260805101600482015260406024820152602160448201527f41413332207061796d61737465722065787069726564206f72206e6f7420647560648201527f65000000000000000000000000000000000000000000000000000000000000006084820152fd5b608482604051907f220266b600000000000000000000000000000000000000000000000000000000825260805101600482015260406024820152601460448201527f41413334207369676e6174757265206572726f720000000000000000000000006064820152fd5b608482604051907f220266b600000000000000000000000000000000000000000000000000000000825260805101600482015260406024820152601760448201527f414132322065787069726564206f72206e6f74206475650000000000000000006064820152fd5b608483604051907f220266b600000000000000000000000000000000000000000000000000000000825260805101600482015260406024820152601460448201527f41413234207369676e6174757265206572726f720000000000000000000000006064820152fd5b9897969594505a9883519961085b73ffffffffffffffffffffffffffffffffffffffff60e08d015116604087015190615482565b15610ac75760807f52b7512c000000000000000000000000000000000000000000000000000000009798999a9b01516040516108dc816108b060208a015160408b015190602084019d8e528960248501615460565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282612c2d565b8651608073ffffffffffffffffffffffffffffffffffffffff60e08301511691015161014051918b61014051928551926101405191f1983d908161014051843e51948251604084019b8c519015918215610abb575b508115610a8b575b50610a065750601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09101160191826040525a90031161097a5750946105ec565b80887f220266b60000000000000000000000000000000000000000000000000000000060a4935260805101600482015260406024820152602760448201527f41413336206f766572207061796d6173746572566572696669636174696f6e4760648201527f61734c696d6974000000000000000000000000000000000000000000000000006084820152fd5b8b610a87610a1261349e565b6040519384937f65c8fd4d0000000000000000000000000000000000000000000000000000000085526080510160048501526024840152600d60648401527f4141333320726576657274656400000000000000000000000000000000000000608484015260a0604484015260a4830190612de9565b0390fd5b9050601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa084019101105f610939565b6040141591505f610931565b608487604051907f220266b600000000000000000000000000000000000000000000000000000000825260805101600482015260406024820152601e60448201527f41413331207061796d6173746572206465706f73697420746f6f206c6f7700006064820152fd5b608487604051907f220266b600000000000000000000000000000000000000000000000000000000825260805101600482015260406024820152601e60448201527f41413236206f76657220766572696669636174696f6e4761734c696d697400006064820152fd5b608488604051907f220266b600000000000000000000000000000000000000000000000000000000825260805101600482015260406024820152601a60448201527f4141323520696e76616c6964206163636f756e74206e6f6e63650000000000006064820152fd5b610c0b91615482565b15610c17578b8061054c565b608488604051907f220266b600000000000000000000000000000000000000000000000000000000825260805101600482015260406024820152601760448201527f41413231206469646e2774207061792070726566756e640000000000000000006064820152fd5b8b903b610cf057608490604051907f220266b600000000000000000000000000000000000000000000000000000000825260805101600482015260406024820152601960448201527f41413230206163636f756e74206e6f74206465706c6f796564000000000000006064820152fd5b610cf861349e565b90610a876040519283927f65c8fd4d00000000000000000000000000000000000000000000000000000000845260805101600484015260606024840152600d60648401527f4141323320726576657274656400000000000000000000000000000000000000608484015260a0604484015260a4830190612de9565b61014051915061053d565b6101408051849052516020819052604090205490985081811115610da85750610140515b97610485565b8103610da2565b80887f220266b6000000000000000000000000000000000000000000000000000000006084935260805101600482015260406024820152601860448201527f41413934206761732076616c756573206f766572666c6f7700000000000000006064820152fd5b60348210610ed05781601411610ec95780359160248110610ec957603411610ec9576024810135608090811c60a0880152601490910135811c90860152606081901c15610e6b5760601c60e085015289806103b3565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4141393820696e76616c6964207061796d6173746572000000000000000000006044820152fd5b6101405180fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4141393320696e76616c6964207061796d6173746572416e64446174610000006044820152fd5b610f3b8160e05184613267565b92610f4684806132a7565b919073ffffffffffffffffffffffffffffffffffffffff610f69602088016132fb565b16956001871461111d5786610f86575b5050019250600101610137565b806040610f9492019061331c565b91873b15610ec957916040519283917f2dd8113300000000000000000000000000000000000000000000000000000000835286604484016040600486015252606483019160648860051b8501019281610140517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee182360301915b8b82106110c357505050505081611054917ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8580950301602485015261014051956131b6565b0381610140518a5af190816110a8575b5061109b57847f86a9f750000000000000000000000000000000000000000000000000000000006101405152600452602461014051fd5b929350839260015f610f79565b610140516110b591612c2d565b61014051610ec9575f611064565b9193967fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9c90879294969703018552863584811215610ec957602061110c600193858394016133bd565b98019501920188969594939161100e565b867f86a9f750000000000000000000000000000000000000000000000000000000006101405152600452602461014051fd5b34610ec95760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec957611186612cde565b3361014051526101405160205260016040610140512001908154916dffffffffffffffffffffffffffff8360081c169283156113945760981c65ffffffffffff1680156113365742106112d85780547fffffffffffffff000000000000000000000000000000000000000000000000ff1690556040805173ffffffffffffffffffffffffffffffffffffffff831681526020810184905233917fb7c918e0e249f999e965cafeb6c664271b3f4317d296461500e71da39f0cbda391a2610140519182918291829173ffffffffffffffffffffffffffffffffffffffff165af161126d612eba565b501561127a576101405180f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f6661696c656420746f207769746864726177207374616b6500000000000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f5374616b65207769746864726177616c206973206e6f742064756500000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f6d7573742063616c6c20756e6c6f636b5374616b6528292066697273740000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f207374616b6520746f2077697468647261770000000000000000000000006044820152fd5b34610ec957610140517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec9573361014051526101405160205260016040610140512001805463ffffffff8160781c169081156115835760ff16156115255765ffffffffffff4216019065ffffffffffff82116114f25780547fffffffffffffff000000000000ffffffffffffffffffffffffffffffffffff001678ffffffffffff00000000000000000000000000000000000000609884901b1617905560405165ffffffffffff909116815233907ffa9b3c14cc825c412c9ed81b3ba365a5b459439403f18829e572ed53a4180f0a90602090a26101405180f35b7f4e487b710000000000000000000000000000000000000000000000000000000061014051526011600452602461014051fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f616c726561647920756e7374616b696e670000000000000000000000000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f6e6f74207374616b6564000000000000000000000000000000000000000000006044820152fd5b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec95761161b611616612cde565b6131f4565b6101405180f35b34610ec95760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec95760043567ffffffffffffffff8111610ec95760206116766116b1923690600401612d01565b60405193849283927f570e1a3600000000000000000000000000000000000000000000000000000000845285600485015260248401916131b6565b03816101405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165af180156117785773ffffffffffffffffffffffffffffffffffffffff916101405191611749575b507f6ca7b80600000000000000000000000000000000000000000000000000000000610140515216600452602461014051fd5b61176b915060203d602011611771575b6117638183612c2d565b81019061318a565b82611716565b503d611759565b6040513d61014051823e3d90fd5b34610ec95760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec9576117bd612cde565b60243567ffffffffffffffff8111610ec9576117dd903690600401612d01565b604051929181908437820190610140518252610140519280610140519303915af4611806612eba565b90610a876040519283927f9941055400000000000000000000000000000000000000000000000000000000845215156004840152604060248401526044830190612de9565b34610ec957610140517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec9576119296118a87f0000000000000000000000000000000000000000000000000000000000000000614ccf565b6118d17f0000000000000000000000000000000000000000000000000000000000000000614e45565b60405190602090611937906118e68385612c2d565b6101405184525f3681376040519586957f0f00000000000000000000000000000000000000000000000000000000000000875260e08588015260e0870190612de9565b908582036040870152612de9565b4660608501523060808501526101405160a085015283810360c0850152818084519283815201930191610140515b82811061197457505050500390f35b835185528695509381019392810192600101611965565b34610ec95761199936612d56565b6119a4929192613824565b6119ad8361303a565b6119b8818585613898565b5061014051927fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f9728480a161014051915b8583106119f9576101b48585614a19565b909193600190611a1f611a0d878987613109565b611a178886613176565b51908861437c565b01940191906119e8565b34610ec95760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec95773ffffffffffffffffffffffffffffffffffffffff611a75612cde565b1661014051526101405160205260206040610140512054604051908152f35b34610ec95760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec95773ffffffffffffffffffffffffffffffffffffffff611ae0612cde565b604051611aec81612bab565b6101405181526101405160208201526101405160408201526101405160608201526080610140519101521661014051526101405160205260a06040610140512065ffffffffffff604051611b3f81612bab565b63ffffffff60018454948584520154916dffffffffffffffffffffffffffff6020820160ff8516151581526040830190828660081c1682528660806060860195878960781c168752019660981c1686526040519788525115156020880152511660408601525116606084015251166080820152f35b34610ec95760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec9576020611bed612cde565b73ffffffffffffffffffffffffffffffffffffffff611c0a612d2f565b91166101405152600182526040610140512077ffffffffffffffffffffffffffffffffffffffffffffffff82165f52825260405f20547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000006040519260401b16178152f35b34610ec95760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec95760043567ffffffffffffffff8111610ec9576101207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8236030112610ec957611cea602091600401612ee9565b604051908152f35b34610ec95760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec957611d29612cde565b6024359033610140515261014051602052604061014051208054808411611e355783611d5491612ead565b90556040805173ffffffffffffffffffffffffffffffffffffffff831681526020810184905233917fd1c19fbcd4551a5edfb66d43d2e337c04837afda3482b42bdf569a8fccdae5fb91a2610140519182918291829173ffffffffffffffffffffffffffffffffffffffff165af1611dca612eba565b5015611dd7576101405180f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6661696c656420746f20776974686472617700000000000000000000000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f576974686472617720616d6f756e7420746f6f206c61726765000000000000006044820152fd5b34610ec95760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec957611eca612cde565b73ffffffffffffffffffffffffffffffffffffffff611ee7612d2f565b91166101405152600160205277ffffffffffffffffffffffffffffffffffffffffffffffff6040610140512091165f52602052602060405f2054604051908152f35b34610ec957610140517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec95760206040517f29a0bca4af4be3421398da00295e58e6d7de38cb492214754cb6a47507dd6f8e8152f35b34610ec957610140517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec9576020611cea6134cb565b34610ec95760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec95760043577ffffffffffffffffffffffffffffffffffffffffffffffff81168103610ec957336101405152600160205277ffffffffffffffffffffffffffffffffffffffffffffffff6040610140512091165f5260205260405f206120528154612e80565b90556101405180f35b34610ec957610140517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec957602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec95760043563ffffffff8116809103610ec957336101405152610140516020526040610140512090801561242957600182015463ffffffff8160781c1682106123cb57612155906dffffffffffffffffffffffffffff349160081c16612e46565b91821561236d576dffffffffffffffffffffffffffff831161230f57546040516122d79161218282612bab565b815265ffffffffffff602082019160018352604081016dffffffffffffffffffffffffffff87168152606082019086825260016080840193610140518552336101405152610140516020526040610140512090518155019451151560ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008754169116178555517fffffffffffffffffffffffffffffffffff0000000000000000000000000000ff6effffffffffffffffffffffffffff008087549360081b16169116178455517fffffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffff72ffffffff0000000000000000000000000000008086549360781b1616911617835551167fffffffffffffff000000000000ffffffffffffffffffffffffffffffffffffff78ffffffffffff0000000000000000000000000000000000000083549260981b169116179055565b60405191825260208201527fa5ae833d0bb1dcd632d98a8b70973e8516812898e19bf27b70071ebc8dc52c0160403392a26101405180f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f7374616b65206f766572666c6f770000000000000000000000000000000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6e6f207374616b652073706563696669656400000000000000000000000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f63616e6e6f7420646563726561736520756e7374616b652074696d65000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f6d757374207370656369667920756e7374616b652064656c61790000000000006044820152fd5b34610ec95760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec9576004357fffffffff000000000000000000000000000000000000000000000000000000008116809103610ec957807f6930d3ee00000000000000000000000000000000000000000000000000000000602092149081156125af575b8115612585575b811561255b575b8115612531575b506040519015158152f35b7f01ffc9a70000000000000000000000000000000000000000000000000000000091501482612526565b7f3e84f021000000000000000000000000000000000000000000000000000000008114915061251f565b7fcf28ef970000000000000000000000000000000000000000000000000000000081149150612518565b7f989ccc580000000000000000000000000000000000000000000000000000000081149150612511565b34612a32576102007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112612a325760043567ffffffffffffffff8111612a325736602382011215612a325761263a903690602481600401359101612ca8565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc36016101c08112612a32576101406040519161267683612bab565b12612a325760405161268781612bf4565b60243573ffffffffffffffffffffffffffffffffffffffff81168103612a3257815260443560208201526064356040820152608435606082015260a435608082015260c43560a082015260e43560c08201526101043573ffffffffffffffffffffffffffffffffffffffff81168103612a325760e082015261012435610100820152610144356101208201528152602081019161016435835260408201906101843582526101a435606084015260808301916101c43583526101e43567ffffffffffffffff8111612a3257612760903690600401612d01565b955a90303303612b4d578651606081015195603f5a0260061c61271060a084015189010111612b25575f9681519182612a6b575b5050505050906127ac915a9003855101963691612ca8565b925a93855161010081015161012082015148018082105f14612a635750975b6127f873ffffffffffffffffffffffffffffffffffffffff60e08401511694518203606084015190614b09565b01925f928161290e5750505173ffffffffffffffffffffffffffffffffffffffff16945b5a900301019485029051928184105f146128ba5750506003811015612887576002036128595760209281611cea929361285481614c2a565b614b28565b7fdeadaa51000000000000000000000000000000000000000000000000000000006101405152602061014051fd5b7f4e487b710000000000000000000000000000000000000000000000000000000061014051526021600452602461014051fd5b816128f0929594969396039073ffffffffffffffffffffffffffffffffffffffff165f525f60205260405f209081540180915590565b5060038410156128875782612909926020951590614ba9565b611cea565b909691878251612921575b50505061281c565b90919293505a926003881015612a365760028803612957575b505060a061294e925a900391015190614b09565b90888080612919565b60a083015191803b15612a32578b925f92836129b3938c8b88604051998a98899788957f7c627b210000000000000000000000000000000000000000000000000000000087526004870152608060248701526084860190612de9565b9202604484015260648301520393f19081612a1d575b50612a1357610a876129d961349e565b6040519182917fad7954bc000000000000000000000000000000000000000000000000000000008352602060048401526024830190612de9565b60a061294e61293a565b5f612a2791612c2d565b5f610140528a6129c9565b5f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b9050976127cb565b915f9291838093602073ffffffffffffffffffffffffffffffffffffffff885116910192f115612a9e575b808080612794565b6127ac9392955060405191612ab161349e565b908151612aca575b505050604052600193909188612a96565b7f1c4fada7374c0a9ee8841fc38afe82932dc0f8e69012e927f061a8bae611a201905191602073ffffffffffffffffffffffffffffffffffffffff855116940151612b1a60405192839283612e2c565b0390a3888080612ab9565b7fdeaddead000000000000000000000000000000000000000000000000000000005f5260205ffd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4141393220696e7465726e616c2063616c6c206f6e6c790000000000000000006044820152fd5b60a0810190811067ffffffffffffffff821117612bc757604052565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b610140810190811067ffffffffffffffff821117612bc757604052565b6060810190811067ffffffffffffffff821117612bc757604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117612bc757604052565b67ffffffffffffffff8111612bc757601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b929192612cb482612c6e565b91612cc26040519384612c2d565b829481845281830111612a32578281602093845f960137010152565b6004359073ffffffffffffffffffffffffffffffffffffffff82168203612a3257565b9181601f84011215612a325782359167ffffffffffffffff8311612a325760208381860195010111612a3257565b6024359077ffffffffffffffffffffffffffffffffffffffffffffffff82168203612a3257565b9060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc830112612a325760043567ffffffffffffffff8111612a325760040182601f82011215612a325780359267ffffffffffffffff8411612a32576020808301928560051b010111612a3257919060243573ffffffffffffffffffffffffffffffffffffffff81168103612a325790565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f602080948051918291828752018686015e5f8582860101520116010190565b604090612e43939281528160208201520190612de9565b90565b91908201809211612e5357565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114612e535760010190565b91908203918211612e5357565b3d15612ee4573d90612ecb82612c6e565b91612ed96040519384612c2d565b82523d5f602084013e565b606090565b604290612ef5816135f4565b612efd6134cb565b91612f07816132fb565b91801561300557905b60c0612f1f606083018361331c565b90816040519182372091612f3660e082018261331c565b908160405191823720926040519473ffffffffffffffffffffffffffffffffffffffff60208701977f29a0bca4af4be3421398da00295e58e6d7de38cb492214754cb6a47507dd6f8e895216604087015260208301356060870152608086015260a085015260808101358285015260a081013560e085015201356101008301526101208201526101208152612fcd61014082612c2d565b519020604051917f19010000000000000000000000000000000000000000000000000000000000008352600283015260228201522090565b50613013604082018261331c565b90816040519182372090612f10565b67ffffffffffffffff8111612bc75760051b60200190565b9061304482613022565b6130516040519182612c2d565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe061307f8294613022565b01905f5b82811061308f57505050565b60209060405161309e81612bab565b6040516130aa81612bf4565b5f81525f848201525f60408201525f60608201525f60808201525f60a08201525f60c08201525f60e08201525f6101008201525f61012082015281525f838201525f60408201525f60608201525f608082015282828501015201613083565b91908110156131495760051b810135907ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee181360301821215612a32570190565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b80518210156131495760209160051b010190565b90816020910312612a32575173ffffffffffffffffffffffffffffffffffffffff81168103612a325790565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe093818652868601375f8582860101520116010190565b7f2da466a7b24304f47e87fa2e1e5a81b9831ce54fec19055ce277ca2f39ba42c4602073ffffffffffffffffffffffffffffffffffffffff61325b348573ffffffffffffffffffffffffffffffffffffffff165f525f60205260405f209081540180915590565b936040519485521692a2565b91908110156131495760051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa181360301821215612a32570190565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215612a32570180359067ffffffffffffffff8211612a3257602001918160051b36038313612a3257565b3573ffffffffffffffffffffffffffffffffffffffff81168103612a325790565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215612a32570180359067ffffffffffffffff8211612a3257602001918136038313612a3257565b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe182360301811215612a3257016020813591019167ffffffffffffffff8211612a32578136038313612a3257565b80359173ffffffffffffffffffffffffffffffffffffffff83168303612a325773ffffffffffffffffffffffffffffffffffffffff612e43931681526020820135602082015261348f61348361344a61342f61341c604087018761336d565b61012060408801526101208701916131b6565b61343c606087018761336d565b9086830360608801526131b6565b6080850135608085015260a085013560a085015260c085013560c085015261347560e086018661336d565b9085830360e08701526131b6565b9261010081019061336d565b916101008185039101526131b6565b3d61080081116134c2575b604051906020818301016040528082525f602083013e90565b506108006134a9565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163014806135cb575b15613533577f000000000000000000000000000000000000000000000000000000000000000090565b60405160208101907f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f82527f000000000000000000000000000000000000000000000000000000000000000060408201527f000000000000000000000000000000000000000000000000000000000000000060608201524660808201523060a082015260a081526135c560c082612c2d565b51902090565b507f0000000000000000000000000000000000000000000000000000000000000000461461350a565b613601604082018261331c565b909161360d8284614c7a565b1561381d5761361b906132fb565b60175f80833c5f51907fef010000000000000000000000000000000000000000000000000000000000007fffffff000000000000000000000000000000000000000000000000000000000083160361375b575060181b91601482116136bb5750506040517fffffffffffffffffffffffffffffffffffffffff000000000000000000000000808060208401941616168252601481526135c5603482612c2d565b81601411612a325760206135c5916040519384917fffffffffffffffffffffffffffffffffffffffff000000000000000000000000808086860199161616875260147fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec83019101603484013781015f8382015203017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282612c2d565b3b156137bf5760646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f6e6f7420616e204549502d373730322064656c656761746500000000000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f73656e64657220686173206e6f20636f646500000000000000000000000000006044820152fd5b5050505f90565b7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005c6138705760017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005d565b7f3ee5aeb5000000000000000000000000000000000000000000000000000000005f5260045ffd5b92919092835f5b8181106138ac5750505050565b6138b68185613176565b516138c2828486613109565b5f915a81519273ffffffffffffffffffffffffffffffffffffffff6138e6826132fb565b168452602081013560208501526080810135936fffffffffffffffffffffffffffffffff8560801c951694604082019060608301968752815260c0820160a0840135815260c0840135906fffffffffffffffffffffffffffffffff8260801c9216916101208501906101008601938452815261396560e087018761331c565b9081614316575b505060405161397a87612ee9565b9960208a019a8b528160405285519586855117825117926effffffffffffffffffffffffffffff60808a01948551179560a08b0196875117895117905117116142b45750519051019051019051019051019051029560408601918783528973ffffffffffffffffffffffffffffffffffffffff60e08951613a0f8b8483511695613a0760408d018d61331c565b929091614fb5565b015116985f99801561428d575b89516040810151905173ffffffffffffffffffffffffffffffffffffffff1680916040519d8e808d8b519360208301947f19822f7c0000000000000000000000000000000000000000000000000000000086526024840192613a7d93615460565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081018252613aad9082612c2d565b51905f6020948194f15f519c3d602003614285575b6040521561419a575015614120575b505073ffffffffffffffffffffffffffffffffffffffff8451166020850151905f52600160205260405f2077ffffffffffffffffffffffffffffffffffffffffffffffff8260401c165f5260205267ffffffffffffffff60405f2091825492613b3984612e80565b905516036140bb575a8603116140565773ffffffffffffffffffffffffffffffffffffffff60e0606094015116613d96575b505073ffffffffffffffffffffffffffffffffffffffff949260a085936080936060613ba29801520135905a900301910152614f15565b9116613d3157613ccc57613bca73ffffffffffffffffffffffffffffffffffffffff91614f15565b9116613c6757613bdc5760010161389f565b60a490604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152602160448201527f41413332207061796d61737465722065787069726564206f72206e6f7420647560648201527f65000000000000000000000000000000000000000000000000000000000000006084820152fd5b608482604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601460448201527f41413334207369676e6174757265206572726f720000000000000000000000006064820152fd5b608482604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601760448201527f414132322065787069726564206f72206e6f74206475650000000000000000006064820152fd5b608483604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601460448201527f41413234207369676e6174757265206572726f720000000000000000000000006064820152fd5b909c9b9a99989796505a9085519d60e08f015173ffffffffffffffffffffffffffffffffffffffff168151613dca91615482565b15613ff157613e1d7f52b7512c00000000000000000000000000000000000000000000000000000000999a9b9c9d9e9f60800151926108b060405193849251905190602084019d8e528960248501615460565b5f8088518b82608073ffffffffffffffffffffffffffffffffffffffff60e08501511693015192865193f1983d90815f843e51948251604084019b8c519015918215613fe5575b508115613fb5575b50613f385750601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09101160191826040525a900311613eb05750948260a0613b6b565b80887f220266b60000000000000000000000000000000000000000000000000000000060a49352600482015260406024820152602760448201527f41413336206f766572207061796d6173746572566572696669636174696f6e4760648201527f61734c696d6974000000000000000000000000000000000000000000000000006084820152fd5b8b610a87613f4461349e565b6040519384937f65c8fd4d00000000000000000000000000000000000000000000000000000000855260048501526024840152600d60648401527f4141333320726576657274656400000000000000000000000000000000000000608484015260a0604484015260a4830190612de9565b9050601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa084019101105f613e6c565b6040141591505f613e64565b608489604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601e60448201527f41413331207061796d6173746572206465706f73697420746f6f206c6f7700006064820152fd5b608489604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601e60448201527f41413236206f76657220766572696669636174696f6e4761734c696d697400006064820152fd5b60848a604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601a60448201527f4141323520696e76616c6964206163636f756e74206e6f6e63650000000000006064820152fd5b61412991615482565b15614135575f80613ad1565b60848a604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601760448201527f41413231206469646e2774207061792070726566756e640000000000000000006064820152fd5b8d903b61420657608490604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601960448201527f41413230206163636f756e74206e6f74206465706c6f796564000000000000006064820152fd5b61420e61349e565b90610a876040519283927f65c8fd4d000000000000000000000000000000000000000000000000000000008452600484015260606024840152600d60648401527f4141323320726576657274656400000000000000000000000000000000000000608484015260a0604484015260a4830190612de9565b5f9150613ac2565b9950815f525f60205260405f20548181115f146142ad57505f5b99613a1c565b81036142a7565b808f7f220266b60000000000000000000000000000000000000000000000000000000060849352600482015260406024820152601860448201527f41413934206761732076616c756573206f766572666c6f7700000000000000006064820152fd5b60348210610ed05781601411612a3257803560601c9160248110612a3257601482013590603411612a32576fffffffffffffffffffffffffffffffff60248193013560801c1660a089015260801c1660808701528015610e6b5760e08601525f8061396c565b9092915a60608201516040519586614397606083018361331c565b5f60038211614a11575b7fffffffff00000000000000000000000000000000000000000000000000000000167f8dd7712f00000000000000000000000000000000000000000000000000000000036148a3575050505f6144ae6145a261443c61446e602095868a01516040519384927f8dd7712f000000000000000000000000000000000000000000000000000000008a8501526040602485015260648401906133bd565b906044830152037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282612c2d565b6108b06040519384927e42dc5300000000000000000000000000000000000000000000000000000000888501526102006024850152610224840190612de9565b614571604484018b60806101a091610120815173ffffffffffffffffffffffffffffffffffffffff8151168652602081015160208701526040810151604087015260608101516060870152838101518487015260a081015160a087015260c081015160c087015273ffffffffffffffffffffffffffffffffffffffff60e08201511660e087015261010081015161010087015201516101208501526020810151610140850152604081015161016085015260608101516101808501520151910152565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc8382030161020484015287612de9565b828151910182305af15f5196604052156145bd575b50505050565b9091929394505f3d602014614896575b7fdeaddead00000000000000000000000000000000000000000000000000000000810361465957608485604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152600f60448201527f41413935206f7574206f662067617300000000000000000000000000000000006064820152fd5b92935090917fdeadaa5100000000000000000000000000000000000000000000000000000000036146bc57506146a16146966146b1925a90612ead565b608084015190612e46565b6040830151836128548295614c2a565b905b5f8080806145b7565b9061472f9060405160208501518551907ff62676f440ff169a3a9afdbf812e89e7f95975ee8e5c31214ffdef631c5f4792602073ffffffffffffffffffffffffffffffffffffffff84511693015161471261349e565b9061472260405192839283612e2c565b0390a36040525a90612ead565b61473f6080840191825190612e46565b915f905a92855161010081015161012082015148018082105f1461488e5750955b61478d73ffffffffffffffffffffffffffffffffffffffff60e08401511693518203606084015190614b09565b01925f928061485f5750505173ffffffffffffffffffffffffffffffffffffffff16935b5a900301019283026040850151928184105f14614813575050806147e6575090816147e0929361285481614c2a565b906146b3565b807f4e487b7100000000000000000000000000000000000000000000000000000000602492526021600452fd5b614848908284939795039073ffffffffffffffffffffffffffffffffffffffff165f525f60205260405f209081540180915590565b506147e6575090825f61485a93614ba9565b6147e0565b9591905161486e575b506147b1565b935090506148875a9360a05f955a900391015190614b09565b905f614868565b905095614760565b5060205f803e5f516145cd565b614a0893506149dc916148e8917e42dc5300000000000000000000000000000000000000000000000000000000602086015261020060248601526102248501916131b6565b6149ab604484018860806101a091610120815173ffffffffffffffffffffffffffffffffffffffff8151168652602081015160208701526040810151604087015260608101516060870152838101518487015260a081015160a087015260c081015160c087015273ffffffffffffffffffffffffffffffffffffffff60e08201511660e087015261010081015161010087015201516101208501526020810151610140850152604081015161016085015260608101516101808501520151910152565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc8382030161020484015284612de9565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101885287612c2d565b60205f876145a2565b5081356143a1565b73ffffffffffffffffffffffffffffffffffffffff168015614aab575f80809381935af1614a45612eba565b5015614a4d57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f41413931206661696c65642073656e6420746f2062656e6566696369617279006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4141393020696e76616c69642062656e656669636961727900000000000000006044820152fd5b90619c408201811115614b2257606491600a9103020490565b50505f90565b9190917f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f6080602083015192519473ffffffffffffffffffffffffffffffffffffffff86511694602073ffffffffffffffffffffffffffffffffffffffff60e089015116970151916040519283525f602084015260408301526060820152a4565b9060807f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f91602084015193519573ffffffffffffffffffffffffffffffffffffffff87511695602073ffffffffffffffffffffffffffffffffffffffff60e08a015116980151926040519384521515602084015260408301526060820152a4565b60208101519051907f67b4fa9642f42120bf031f3051d1824b0fe25627945b27b8a6a65d5761d5482e60208073ffffffffffffffffffffffffffffffffffffffff855116940151604051908152a3565b90600211614cca57357fffffffffffffffffffffffffffffffffffffffff000000000000000000000000167f77020000000000000000000000000000000000000000000000000000000000001490565b505f90565b60ff8114614d2e5760ff811690601f8211614d065760405191614cf3604084612c2d565b6020808452838101919036833783525290565b7fb3512b0c000000000000000000000000000000000000000000000000000000005f5260045ffd5b506040515f6002548060011c9160018216918215614e3b575b602084108314614e0e578385528492908115614dd15750600114614d72575b612e4392500382612c2d565b5060025f90815290917f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace5b818310614db5575050906020612e4392820101614d66565b6020919350806001915483858801015201910190918392614d9d565b60209250612e439491507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001682840152151560051b820101614d66565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b92607f1692614d47565b60ff8114614e695760ff811690601f8211614d065760405191614cf3604084612c2d565b506040515f6003548060011c9160018216918215614f0b575b602084108314614e0e578385528492908115614dd15750600114614eac57612e4392500382612c2d565b5060035f90815290917fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b5b818310614eef575050906020612e4392820101614d66565b6020919350806001915483858801015201910190918392614ed7565b92607f1692614e82565b8015614fae575f60408051614f2981612c11565b828152826020820152015273ffffffffffffffffffffffffffffffffffffffff81169065ffffffffffff8160a01c16908115614fa0575b60409060d01c9165ffffffffffff825191614f7a83612c11565b8583528460208401521691829101524211908115614f9757509091565b90504211159091565b65ffffffffffff9150614f60565b505f905f90565b929190915f9080614fc8575b5050505050565b83519473ffffffffffffffffffffffffffffffffffffffff86511695614fee8386614c7a565b61535f5750853b6152fa576014821061529557604085510151602060405180927f570e1a36000000000000000000000000000000000000000000000000000000008252826004830152818781615048602482018a8d6131b6565b039273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690f190811561528a57849161526b575b5073ffffffffffffffffffffffffffffffffffffffff811680156152065787036151a1573b1561513c5750601411615139577fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d91604091503573ffffffffffffffffffffffffffffffffffffffff60e06020860151955101511673ffffffffffffffffffffffffffffffffffffffff83519260601c1682526020820152a35f80808080614fc1565b80fd5b608490604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152602060448201527f4141313520696e6974436f6465206d757374206372656174652073656e6465726064820152fd5b608482604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152602060448201527f4141313420696e6974436f6465206d7573742072657475726e2073656e6465726064820152fd5b608483604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601b60448201527f4141313320696e6974436f6465206661696c6564206f72204f4f4700000000006064820152fd5b615284915060203d602011611771576117638183612c2d565b5f615091565b6040513d86823e3d90fd5b608490604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601760448201527f4141393920696e6974436f646520746f6f20736d616c6c0000000000000000006064820152fd5b608490604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601f60448201527f414131302073656e64657220616c726561647920636f6e7374727563746564006064820152fd5b945050919050601482116153735750505050565b604073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169301519082601411612a3257833b15612a32575f809461542f96604051978896879586937fc09ad0d900000000000000000000000000000000000000000000000000000000855260048501526040602485015260147fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec60448601930191016131b6565b0393f1801561545557615445575b8080806145b7565b5f61544f91612c2d565b5f61543d565b6040513d5f823e3d90fd5b615478604092959493956060835260608301906133bd565b9460208201520152565b73ffffffffffffffffffffffffffffffffffffffff165f525f60205260405f2090815481811061381d5703905560019056fea2646970667358221220a2ee7c02d47f72772240d0dfa7174d99b6049a68ccdf3d4434c3918f6bd9c1e164736f6c634300081c003360a08060405234602f57336080526104c19081610034823960805181818160d80152818161023401526102e10152f35b5f80fdfe60806040526004361015610011575f80fd5b5f3560e01c8063570e1a3614610258578063b0d691fe146101ea5763c09ad0d91461003a575f80fd5b346101e65760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101e65760043573ffffffffffffffffffffffffffffffffffffffff811681036101e65760243567ffffffffffffffff81116101e657366023820112156101e6575f916100bd83923690602481600401359101610384565b906100ff73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163314610426565b82602083519301915af11561011057005b3d61080081116101dd575b60c460405160208382010160405282815260208101925f843e7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f6040519485937f65c8fd4d0000000000000000000000000000000000000000000000000000000085525f6004860152606060248601528260648601527f4141313320454950373730322073656e64657220696e6974206661696c656400608486015260a060448601525180918160a48701528686015e5f85828601015201168101030190fd5b5061080061011b565b5f80fd5b346101e6575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101e657602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b346101e65760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101e65760043567ffffffffffffffff81116101e657366023820112156101e65780600401359067ffffffffffffffff82116101e65736602483830101116101e6575f9161030873ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163314610426565b806014116101e6576020916103455f927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec36910160388401610384565b90826024858451940192013560601c5af161037c575b60209073ffffffffffffffffffffffffffffffffffffffff60405191168152f35b505f5161035b565b92919267ffffffffffffffff82116103f957604051917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f81601f8401160116830183811067ffffffffffffffff8211176103f9576040528294818452818301116101e6578281602093845f960137010152565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b1561042d57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602060248201527f414139372073686f756c642063616c6c2066726f6d20456e747279506f696e746044820152fdfea26469706673582212206423798798d408242e814ed5c031f1afcdccad1146c1c11fab88cce1fdaa4c4a64736f6c634300081c0033", + "deployedBytecode": "0x6101606040526004361015610024575b3615610019575f80fd5b610022336131f4565b005b5f610140525f3560e01c806242dc53146125d957806301ffc9a7146124875780630396cb60146120cc57806309ccb8801461205b5780630bd28e3b14611fbf57806313c65a6e14611f84578063154e58dc14611f295780631b2e01b814611e93578063205c287814611cf257806322cdde4c14611c6e57806335567e1a14611bb45780635287ce1214611a9457806370a0823114611a29578063765e827f1461198b57806384b0196e1461184b578063850aaf62146117865780639b249f6914611622578063b760faf9146115e1578063bb9fe6bf146113f2578063c23a5cea1461114f5763dbed18e00361000f5734610ec95761012136612d56565b6101005260e052610130613824565b6101405190815b60e0518110610f2e575061014a8261303a565b61012052610140516080526101405160c0525b60e05160c0511061029b577fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f9726101405161014051a161014051608081905290815b60e05181106101e1576101b48361010051614a19565b610140517f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005d6101405180f35b6102436101f18260e05185613267565b73ffffffffffffffffffffffffffffffffffffffff610212602083016132fb565b167f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d6101405161014051a2806132a7565b9061014051915b80831061025c5750505060010161019e565b909194600190610289610270888587613109565b61027f60805161012051613176565b519060805161437c565b0195816080510160805201919061024a565b6102aa60c05160e05183613267565b73ffffffffffffffffffffffffffffffffffffffff6102d860206102ce84806132a7565b60a05293016132fb565b61014051911691905b60a05181106103055750505060a05160805101608052600160c0510160c05261015d565b610316816080510161012051613176565b516103248260a05185613109565b61014051915a81519273ffffffffffffffffffffffffffffffffffffffff61034b826132fb565b168452602081810135908501526fffffffffffffffffffffffffffffffff6080808301358281166060880152811c604087015260a083013560c0808801919091528301359182166101008701521c6101208501526103ac60e082018261331c565b9081610e15575b5050604051936103c282612ee9565b6020850152846040526040810151946effffffffffffffffffffffffffffff8660c08401511760608401511760808401511760a084015117610100840151176101208401511711610daf5750604081015160608201510160808201510160a08201510160c0820151016101008201510294856040860152845173ffffffffffffffffffffffffffffffffffffffff60e08183511692610475898d61046960408b018b61331c565b92909160805101614fb5565b0151169661014051978015610d7e575b87516040810151905173ffffffffffffffffffffffffffffffffffffffff169061014051506040519a8b8960208d01519260208301937f19822f7c00000000000000000000000000000000000000000000000000000000855260248401926104ec93615460565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081018d5261051c908d612c2d565b61014051908c5190846101405190602095f161014051519a3d602003610d73575b60405215610c80575015610c02575b505073ffffffffffffffffffffffffffffffffffffffff825116602083015190610140515260016020526040610140512077ffffffffffffffffffffffffffffffffffffffffffffffff8260401c165f5260205267ffffffffffffffff60405f20918254926105ba84612e80565b90551603610b99575a840311610b305760e0015160609073ffffffffffffffffffffffffffffffffffffffff16610827575b73ffffffffffffffffffffffffffffffffffffffff949260a0859360809360606106219801520135905a900301910152614f15565b911685036107be576107555761064b73ffffffffffffffffffffffffffffffffffffffff91614f15565b91166106ec5761065d576001016102e1565b60a490604051907f220266b600000000000000000000000000000000000000000000000000000000825260805101600482015260406024820152602160448201527f41413332207061796d61737465722065787069726564206f72206e6f7420647560648201527f65000000000000000000000000000000000000000000000000000000000000006084820152fd5b608482604051907f220266b600000000000000000000000000000000000000000000000000000000825260805101600482015260406024820152601460448201527f41413334207369676e6174757265206572726f720000000000000000000000006064820152fd5b608482604051907f220266b600000000000000000000000000000000000000000000000000000000825260805101600482015260406024820152601760448201527f414132322065787069726564206f72206e6f74206475650000000000000000006064820152fd5b608483604051907f220266b600000000000000000000000000000000000000000000000000000000825260805101600482015260406024820152601460448201527f41413234207369676e6174757265206572726f720000000000000000000000006064820152fd5b9897969594505a9883519961085b73ffffffffffffffffffffffffffffffffffffffff60e08d015116604087015190615482565b15610ac75760807f52b7512c000000000000000000000000000000000000000000000000000000009798999a9b01516040516108dc816108b060208a015160408b015190602084019d8e528960248501615460565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282612c2d565b8651608073ffffffffffffffffffffffffffffffffffffffff60e08301511691015161014051918b61014051928551926101405191f1983d908161014051843e51948251604084019b8c519015918215610abb575b508115610a8b575b50610a065750601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09101160191826040525a90031161097a5750946105ec565b80887f220266b60000000000000000000000000000000000000000000000000000000060a4935260805101600482015260406024820152602760448201527f41413336206f766572207061796d6173746572566572696669636174696f6e4760648201527f61734c696d6974000000000000000000000000000000000000000000000000006084820152fd5b8b610a87610a1261349e565b6040519384937f65c8fd4d0000000000000000000000000000000000000000000000000000000085526080510160048501526024840152600d60648401527f4141333320726576657274656400000000000000000000000000000000000000608484015260a0604484015260a4830190612de9565b0390fd5b9050601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa084019101105f610939565b6040141591505f610931565b608487604051907f220266b600000000000000000000000000000000000000000000000000000000825260805101600482015260406024820152601e60448201527f41413331207061796d6173746572206465706f73697420746f6f206c6f7700006064820152fd5b608487604051907f220266b600000000000000000000000000000000000000000000000000000000825260805101600482015260406024820152601e60448201527f41413236206f76657220766572696669636174696f6e4761734c696d697400006064820152fd5b608488604051907f220266b600000000000000000000000000000000000000000000000000000000825260805101600482015260406024820152601a60448201527f4141323520696e76616c6964206163636f756e74206e6f6e63650000000000006064820152fd5b610c0b91615482565b15610c17578b8061054c565b608488604051907f220266b600000000000000000000000000000000000000000000000000000000825260805101600482015260406024820152601760448201527f41413231206469646e2774207061792070726566756e640000000000000000006064820152fd5b8b903b610cf057608490604051907f220266b600000000000000000000000000000000000000000000000000000000825260805101600482015260406024820152601960448201527f41413230206163636f756e74206e6f74206465706c6f796564000000000000006064820152fd5b610cf861349e565b90610a876040519283927f65c8fd4d00000000000000000000000000000000000000000000000000000000845260805101600484015260606024840152600d60648401527f4141323320726576657274656400000000000000000000000000000000000000608484015260a0604484015260a4830190612de9565b61014051915061053d565b6101408051849052516020819052604090205490985081811115610da85750610140515b97610485565b8103610da2565b80887f220266b6000000000000000000000000000000000000000000000000000000006084935260805101600482015260406024820152601860448201527f41413934206761732076616c756573206f766572666c6f7700000000000000006064820152fd5b60348210610ed05781601411610ec95780359160248110610ec957603411610ec9576024810135608090811c60a0880152601490910135811c90860152606081901c15610e6b5760601c60e085015289806103b3565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4141393820696e76616c6964207061796d6173746572000000000000000000006044820152fd5b6101405180fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4141393320696e76616c6964207061796d6173746572416e64446174610000006044820152fd5b610f3b8160e05184613267565b92610f4684806132a7565b919073ffffffffffffffffffffffffffffffffffffffff610f69602088016132fb565b16956001871461111d5786610f86575b5050019250600101610137565b806040610f9492019061331c565b91873b15610ec957916040519283917f2dd8113300000000000000000000000000000000000000000000000000000000835286604484016040600486015252606483019160648860051b8501019281610140517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee182360301915b8b82106110c357505050505081611054917ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8580950301602485015261014051956131b6565b0381610140518a5af190816110a8575b5061109b57847f86a9f750000000000000000000000000000000000000000000000000000000006101405152600452602461014051fd5b929350839260015f610f79565b610140516110b591612c2d565b61014051610ec9575f611064565b9193967fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9c90879294969703018552863584811215610ec957602061110c600193858394016133bd565b98019501920188969594939161100e565b867f86a9f750000000000000000000000000000000000000000000000000000000006101405152600452602461014051fd5b34610ec95760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec957611186612cde565b3361014051526101405160205260016040610140512001908154916dffffffffffffffffffffffffffff8360081c169283156113945760981c65ffffffffffff1680156113365742106112d85780547fffffffffffffff000000000000000000000000000000000000000000000000ff1690556040805173ffffffffffffffffffffffffffffffffffffffff831681526020810184905233917fb7c918e0e249f999e965cafeb6c664271b3f4317d296461500e71da39f0cbda391a2610140519182918291829173ffffffffffffffffffffffffffffffffffffffff165af161126d612eba565b501561127a576101405180f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f6661696c656420746f207769746864726177207374616b6500000000000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f5374616b65207769746864726177616c206973206e6f742064756500000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f6d7573742063616c6c20756e6c6f636b5374616b6528292066697273740000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f207374616b6520746f2077697468647261770000000000000000000000006044820152fd5b34610ec957610140517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec9573361014051526101405160205260016040610140512001805463ffffffff8160781c169081156115835760ff16156115255765ffffffffffff4216019065ffffffffffff82116114f25780547fffffffffffffff000000000000ffffffffffffffffffffffffffffffffffff001678ffffffffffff00000000000000000000000000000000000000609884901b1617905560405165ffffffffffff909116815233907ffa9b3c14cc825c412c9ed81b3ba365a5b459439403f18829e572ed53a4180f0a90602090a26101405180f35b7f4e487b710000000000000000000000000000000000000000000000000000000061014051526011600452602461014051fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f616c726561647920756e7374616b696e670000000000000000000000000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f6e6f74207374616b6564000000000000000000000000000000000000000000006044820152fd5b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec95761161b611616612cde565b6131f4565b6101405180f35b34610ec95760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec95760043567ffffffffffffffff8111610ec95760206116766116b1923690600401612d01565b60405193849283927f570e1a3600000000000000000000000000000000000000000000000000000000845285600485015260248401916131b6565b03816101405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165af180156117785773ffffffffffffffffffffffffffffffffffffffff916101405191611749575b507f6ca7b80600000000000000000000000000000000000000000000000000000000610140515216600452602461014051fd5b61176b915060203d602011611771575b6117638183612c2d565b81019061318a565b82611716565b503d611759565b6040513d61014051823e3d90fd5b34610ec95760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec9576117bd612cde565b60243567ffffffffffffffff8111610ec9576117dd903690600401612d01565b604051929181908437820190610140518252610140519280610140519303915af4611806612eba565b90610a876040519283927f9941055400000000000000000000000000000000000000000000000000000000845215156004840152604060248401526044830190612de9565b34610ec957610140517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec9576119296118a87f0000000000000000000000000000000000000000000000000000000000000000614ccf565b6118d17f0000000000000000000000000000000000000000000000000000000000000000614e45565b60405190602090611937906118e68385612c2d565b6101405184525f3681376040519586957f0f00000000000000000000000000000000000000000000000000000000000000875260e08588015260e0870190612de9565b908582036040870152612de9565b4660608501523060808501526101405160a085015283810360c0850152818084519283815201930191610140515b82811061197457505050500390f35b835185528695509381019392810192600101611965565b34610ec95761199936612d56565b6119a4929192613824565b6119ad8361303a565b6119b8818585613898565b5061014051927fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f9728480a161014051915b8583106119f9576101b48585614a19565b909193600190611a1f611a0d878987613109565b611a178886613176565b51908861437c565b01940191906119e8565b34610ec95760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec95773ffffffffffffffffffffffffffffffffffffffff611a75612cde565b1661014051526101405160205260206040610140512054604051908152f35b34610ec95760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec95773ffffffffffffffffffffffffffffffffffffffff611ae0612cde565b604051611aec81612bab565b6101405181526101405160208201526101405160408201526101405160608201526080610140519101521661014051526101405160205260a06040610140512065ffffffffffff604051611b3f81612bab565b63ffffffff60018454948584520154916dffffffffffffffffffffffffffff6020820160ff8516151581526040830190828660081c1682528660806060860195878960781c168752019660981c1686526040519788525115156020880152511660408601525116606084015251166080820152f35b34610ec95760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec9576020611bed612cde565b73ffffffffffffffffffffffffffffffffffffffff611c0a612d2f565b91166101405152600182526040610140512077ffffffffffffffffffffffffffffffffffffffffffffffff82165f52825260405f20547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000006040519260401b16178152f35b34610ec95760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec95760043567ffffffffffffffff8111610ec9576101207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8236030112610ec957611cea602091600401612ee9565b604051908152f35b34610ec95760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec957611d29612cde565b6024359033610140515261014051602052604061014051208054808411611e355783611d5491612ead565b90556040805173ffffffffffffffffffffffffffffffffffffffff831681526020810184905233917fd1c19fbcd4551a5edfb66d43d2e337c04837afda3482b42bdf569a8fccdae5fb91a2610140519182918291829173ffffffffffffffffffffffffffffffffffffffff165af1611dca612eba565b5015611dd7576101405180f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6661696c656420746f20776974686472617700000000000000000000000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f576974686472617720616d6f756e7420746f6f206c61726765000000000000006044820152fd5b34610ec95760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec957611eca612cde565b73ffffffffffffffffffffffffffffffffffffffff611ee7612d2f565b91166101405152600160205277ffffffffffffffffffffffffffffffffffffffffffffffff6040610140512091165f52602052602060405f2054604051908152f35b34610ec957610140517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec95760206040517f29a0bca4af4be3421398da00295e58e6d7de38cb492214754cb6a47507dd6f8e8152f35b34610ec957610140517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec9576020611cea6134cb565b34610ec95760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec95760043577ffffffffffffffffffffffffffffffffffffffffffffffff81168103610ec957336101405152600160205277ffffffffffffffffffffffffffffffffffffffffffffffff6040610140512091165f5260205260405f206120528154612e80565b90556101405180f35b34610ec957610140517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec957602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec95760043563ffffffff8116809103610ec957336101405152610140516020526040610140512090801561242957600182015463ffffffff8160781c1682106123cb57612155906dffffffffffffffffffffffffffff349160081c16612e46565b91821561236d576dffffffffffffffffffffffffffff831161230f57546040516122d79161218282612bab565b815265ffffffffffff602082019160018352604081016dffffffffffffffffffffffffffff87168152606082019086825260016080840193610140518552336101405152610140516020526040610140512090518155019451151560ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008754169116178555517fffffffffffffffffffffffffffffffffff0000000000000000000000000000ff6effffffffffffffffffffffffffff008087549360081b16169116178455517fffffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffff72ffffffff0000000000000000000000000000008086549360781b1616911617835551167fffffffffffffff000000000000ffffffffffffffffffffffffffffffffffffff78ffffffffffff0000000000000000000000000000000000000083549260981b169116179055565b60405191825260208201527fa5ae833d0bb1dcd632d98a8b70973e8516812898e19bf27b70071ebc8dc52c0160403392a26101405180f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f7374616b65206f766572666c6f770000000000000000000000000000000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6e6f207374616b652073706563696669656400000000000000000000000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f63616e6e6f7420646563726561736520756e7374616b652074696d65000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f6d757374207370656369667920756e7374616b652064656c61790000000000006044820152fd5b34610ec95760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec9576004357fffffffff000000000000000000000000000000000000000000000000000000008116809103610ec957807f6930d3ee00000000000000000000000000000000000000000000000000000000602092149081156125af575b8115612585575b811561255b575b8115612531575b506040519015158152f35b7f01ffc9a70000000000000000000000000000000000000000000000000000000091501482612526565b7f3e84f021000000000000000000000000000000000000000000000000000000008114915061251f565b7fcf28ef970000000000000000000000000000000000000000000000000000000081149150612518565b7f989ccc580000000000000000000000000000000000000000000000000000000081149150612511565b34612a32576102007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112612a325760043567ffffffffffffffff8111612a325736602382011215612a325761263a903690602481600401359101612ca8565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc36016101c08112612a32576101406040519161267683612bab565b12612a325760405161268781612bf4565b60243573ffffffffffffffffffffffffffffffffffffffff81168103612a3257815260443560208201526064356040820152608435606082015260a435608082015260c43560a082015260e43560c08201526101043573ffffffffffffffffffffffffffffffffffffffff81168103612a325760e082015261012435610100820152610144356101208201528152602081019161016435835260408201906101843582526101a435606084015260808301916101c43583526101e43567ffffffffffffffff8111612a3257612760903690600401612d01565b955a90303303612b4d578651606081015195603f5a0260061c61271060a084015189010111612b25575f9681519182612a6b575b5050505050906127ac915a9003855101963691612ca8565b925a93855161010081015161012082015148018082105f14612a635750975b6127f873ffffffffffffffffffffffffffffffffffffffff60e08401511694518203606084015190614b09565b01925f928161290e5750505173ffffffffffffffffffffffffffffffffffffffff16945b5a900301019485029051928184105f146128ba5750506003811015612887576002036128595760209281611cea929361285481614c2a565b614b28565b7fdeadaa51000000000000000000000000000000000000000000000000000000006101405152602061014051fd5b7f4e487b710000000000000000000000000000000000000000000000000000000061014051526021600452602461014051fd5b816128f0929594969396039073ffffffffffffffffffffffffffffffffffffffff165f525f60205260405f209081540180915590565b5060038410156128875782612909926020951590614ba9565b611cea565b909691878251612921575b50505061281c565b90919293505a926003881015612a365760028803612957575b505060a061294e925a900391015190614b09565b90888080612919565b60a083015191803b15612a32578b925f92836129b3938c8b88604051998a98899788957f7c627b210000000000000000000000000000000000000000000000000000000087526004870152608060248701526084860190612de9565b9202604484015260648301520393f19081612a1d575b50612a1357610a876129d961349e565b6040519182917fad7954bc000000000000000000000000000000000000000000000000000000008352602060048401526024830190612de9565b60a061294e61293a565b5f612a2791612c2d565b5f610140528a6129c9565b5f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b9050976127cb565b915f9291838093602073ffffffffffffffffffffffffffffffffffffffff885116910192f115612a9e575b808080612794565b6127ac9392955060405191612ab161349e565b908151612aca575b505050604052600193909188612a96565b7f1c4fada7374c0a9ee8841fc38afe82932dc0f8e69012e927f061a8bae611a201905191602073ffffffffffffffffffffffffffffffffffffffff855116940151612b1a60405192839283612e2c565b0390a3888080612ab9565b7fdeaddead000000000000000000000000000000000000000000000000000000005f5260205ffd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4141393220696e7465726e616c2063616c6c206f6e6c790000000000000000006044820152fd5b60a0810190811067ffffffffffffffff821117612bc757604052565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b610140810190811067ffffffffffffffff821117612bc757604052565b6060810190811067ffffffffffffffff821117612bc757604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117612bc757604052565b67ffffffffffffffff8111612bc757601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b929192612cb482612c6e565b91612cc26040519384612c2d565b829481845281830111612a32578281602093845f960137010152565b6004359073ffffffffffffffffffffffffffffffffffffffff82168203612a3257565b9181601f84011215612a325782359167ffffffffffffffff8311612a325760208381860195010111612a3257565b6024359077ffffffffffffffffffffffffffffffffffffffffffffffff82168203612a3257565b9060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc830112612a325760043567ffffffffffffffff8111612a325760040182601f82011215612a325780359267ffffffffffffffff8411612a32576020808301928560051b010111612a3257919060243573ffffffffffffffffffffffffffffffffffffffff81168103612a325790565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f602080948051918291828752018686015e5f8582860101520116010190565b604090612e43939281528160208201520190612de9565b90565b91908201809211612e5357565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114612e535760010190565b91908203918211612e5357565b3d15612ee4573d90612ecb82612c6e565b91612ed96040519384612c2d565b82523d5f602084013e565b606090565b604290612ef5816135f4565b612efd6134cb565b91612f07816132fb565b91801561300557905b60c0612f1f606083018361331c565b90816040519182372091612f3660e082018261331c565b908160405191823720926040519473ffffffffffffffffffffffffffffffffffffffff60208701977f29a0bca4af4be3421398da00295e58e6d7de38cb492214754cb6a47507dd6f8e895216604087015260208301356060870152608086015260a085015260808101358285015260a081013560e085015201356101008301526101208201526101208152612fcd61014082612c2d565b519020604051917f19010000000000000000000000000000000000000000000000000000000000008352600283015260228201522090565b50613013604082018261331c565b90816040519182372090612f10565b67ffffffffffffffff8111612bc75760051b60200190565b9061304482613022565b6130516040519182612c2d565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe061307f8294613022565b01905f5b82811061308f57505050565b60209060405161309e81612bab565b6040516130aa81612bf4565b5f81525f848201525f60408201525f60608201525f60808201525f60a08201525f60c08201525f60e08201525f6101008201525f61012082015281525f838201525f60408201525f60608201525f608082015282828501015201613083565b91908110156131495760051b810135907ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee181360301821215612a32570190565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b80518210156131495760209160051b010190565b90816020910312612a32575173ffffffffffffffffffffffffffffffffffffffff81168103612a325790565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe093818652868601375f8582860101520116010190565b7f2da466a7b24304f47e87fa2e1e5a81b9831ce54fec19055ce277ca2f39ba42c4602073ffffffffffffffffffffffffffffffffffffffff61325b348573ffffffffffffffffffffffffffffffffffffffff165f525f60205260405f209081540180915590565b936040519485521692a2565b91908110156131495760051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa181360301821215612a32570190565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215612a32570180359067ffffffffffffffff8211612a3257602001918160051b36038313612a3257565b3573ffffffffffffffffffffffffffffffffffffffff81168103612a325790565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215612a32570180359067ffffffffffffffff8211612a3257602001918136038313612a3257565b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe182360301811215612a3257016020813591019167ffffffffffffffff8211612a32578136038313612a3257565b80359173ffffffffffffffffffffffffffffffffffffffff83168303612a325773ffffffffffffffffffffffffffffffffffffffff612e43931681526020820135602082015261348f61348361344a61342f61341c604087018761336d565b61012060408801526101208701916131b6565b61343c606087018761336d565b9086830360608801526131b6565b6080850135608085015260a085013560a085015260c085013560c085015261347560e086018661336d565b9085830360e08701526131b6565b9261010081019061336d565b916101008185039101526131b6565b3d61080081116134c2575b604051906020818301016040528082525f602083013e90565b506108006134a9565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163014806135cb575b15613533577f000000000000000000000000000000000000000000000000000000000000000090565b60405160208101907f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f82527f000000000000000000000000000000000000000000000000000000000000000060408201527f000000000000000000000000000000000000000000000000000000000000000060608201524660808201523060a082015260a081526135c560c082612c2d565b51902090565b507f0000000000000000000000000000000000000000000000000000000000000000461461350a565b613601604082018261331c565b909161360d8284614c7a565b1561381d5761361b906132fb565b60175f80833c5f51907fef010000000000000000000000000000000000000000000000000000000000007fffffff000000000000000000000000000000000000000000000000000000000083160361375b575060181b91601482116136bb5750506040517fffffffffffffffffffffffffffffffffffffffff000000000000000000000000808060208401941616168252601481526135c5603482612c2d565b81601411612a325760206135c5916040519384917fffffffffffffffffffffffffffffffffffffffff000000000000000000000000808086860199161616875260147fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec83019101603484013781015f8382015203017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282612c2d565b3b156137bf5760646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f6e6f7420616e204549502d373730322064656c656761746500000000000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f73656e64657220686173206e6f20636f646500000000000000000000000000006044820152fd5b5050505f90565b7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005c6138705760017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005d565b7f3ee5aeb5000000000000000000000000000000000000000000000000000000005f5260045ffd5b92919092835f5b8181106138ac5750505050565b6138b68185613176565b516138c2828486613109565b5f915a81519273ffffffffffffffffffffffffffffffffffffffff6138e6826132fb565b168452602081013560208501526080810135936fffffffffffffffffffffffffffffffff8560801c951694604082019060608301968752815260c0820160a0840135815260c0840135906fffffffffffffffffffffffffffffffff8260801c9216916101208501906101008601938452815261396560e087018761331c565b9081614316575b505060405161397a87612ee9565b9960208a019a8b528160405285519586855117825117926effffffffffffffffffffffffffffff60808a01948551179560a08b0196875117895117905117116142b45750519051019051019051019051019051029560408601918783528973ffffffffffffffffffffffffffffffffffffffff60e08951613a0f8b8483511695613a0760408d018d61331c565b929091614fb5565b015116985f99801561428d575b89516040810151905173ffffffffffffffffffffffffffffffffffffffff1680916040519d8e808d8b519360208301947f19822f7c0000000000000000000000000000000000000000000000000000000086526024840192613a7d93615460565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081018252613aad9082612c2d565b51905f6020948194f15f519c3d602003614285575b6040521561419a575015614120575b505073ffffffffffffffffffffffffffffffffffffffff8451166020850151905f52600160205260405f2077ffffffffffffffffffffffffffffffffffffffffffffffff8260401c165f5260205267ffffffffffffffff60405f2091825492613b3984612e80565b905516036140bb575a8603116140565773ffffffffffffffffffffffffffffffffffffffff60e0606094015116613d96575b505073ffffffffffffffffffffffffffffffffffffffff949260a085936080936060613ba29801520135905a900301910152614f15565b9116613d3157613ccc57613bca73ffffffffffffffffffffffffffffffffffffffff91614f15565b9116613c6757613bdc5760010161389f565b60a490604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152602160448201527f41413332207061796d61737465722065787069726564206f72206e6f7420647560648201527f65000000000000000000000000000000000000000000000000000000000000006084820152fd5b608482604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601460448201527f41413334207369676e6174757265206572726f720000000000000000000000006064820152fd5b608482604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601760448201527f414132322065787069726564206f72206e6f74206475650000000000000000006064820152fd5b608483604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601460448201527f41413234207369676e6174757265206572726f720000000000000000000000006064820152fd5b909c9b9a99989796505a9085519d60e08f015173ffffffffffffffffffffffffffffffffffffffff168151613dca91615482565b15613ff157613e1d7f52b7512c00000000000000000000000000000000000000000000000000000000999a9b9c9d9e9f60800151926108b060405193849251905190602084019d8e528960248501615460565b5f8088518b82608073ffffffffffffffffffffffffffffffffffffffff60e08501511693015192865193f1983d90815f843e51948251604084019b8c519015918215613fe5575b508115613fb5575b50613f385750601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09101160191826040525a900311613eb05750948260a0613b6b565b80887f220266b60000000000000000000000000000000000000000000000000000000060a49352600482015260406024820152602760448201527f41413336206f766572207061796d6173746572566572696669636174696f6e4760648201527f61734c696d6974000000000000000000000000000000000000000000000000006084820152fd5b8b610a87613f4461349e565b6040519384937f65c8fd4d00000000000000000000000000000000000000000000000000000000855260048501526024840152600d60648401527f4141333320726576657274656400000000000000000000000000000000000000608484015260a0604484015260a4830190612de9565b9050601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa084019101105f613e6c565b6040141591505f613e64565b608489604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601e60448201527f41413331207061796d6173746572206465706f73697420746f6f206c6f7700006064820152fd5b608489604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601e60448201527f41413236206f76657220766572696669636174696f6e4761734c696d697400006064820152fd5b60848a604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601a60448201527f4141323520696e76616c6964206163636f756e74206e6f6e63650000000000006064820152fd5b61412991615482565b15614135575f80613ad1565b60848a604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601760448201527f41413231206469646e2774207061792070726566756e640000000000000000006064820152fd5b8d903b61420657608490604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601960448201527f41413230206163636f756e74206e6f74206465706c6f796564000000000000006064820152fd5b61420e61349e565b90610a876040519283927f65c8fd4d000000000000000000000000000000000000000000000000000000008452600484015260606024840152600d60648401527f4141323320726576657274656400000000000000000000000000000000000000608484015260a0604484015260a4830190612de9565b5f9150613ac2565b9950815f525f60205260405f20548181115f146142ad57505f5b99613a1c565b81036142a7565b808f7f220266b60000000000000000000000000000000000000000000000000000000060849352600482015260406024820152601860448201527f41413934206761732076616c756573206f766572666c6f7700000000000000006064820152fd5b60348210610ed05781601411612a3257803560601c9160248110612a3257601482013590603411612a32576fffffffffffffffffffffffffffffffff60248193013560801c1660a089015260801c1660808701528015610e6b5760e08601525f8061396c565b9092915a60608201516040519586614397606083018361331c565b5f60038211614a11575b7fffffffff00000000000000000000000000000000000000000000000000000000167f8dd7712f00000000000000000000000000000000000000000000000000000000036148a3575050505f6144ae6145a261443c61446e602095868a01516040519384927f8dd7712f000000000000000000000000000000000000000000000000000000008a8501526040602485015260648401906133bd565b906044830152037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282612c2d565b6108b06040519384927e42dc5300000000000000000000000000000000000000000000000000000000888501526102006024850152610224840190612de9565b614571604484018b60806101a091610120815173ffffffffffffffffffffffffffffffffffffffff8151168652602081015160208701526040810151604087015260608101516060870152838101518487015260a081015160a087015260c081015160c087015273ffffffffffffffffffffffffffffffffffffffff60e08201511660e087015261010081015161010087015201516101208501526020810151610140850152604081015161016085015260608101516101808501520151910152565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc8382030161020484015287612de9565b828151910182305af15f5196604052156145bd575b50505050565b9091929394505f3d602014614896575b7fdeaddead00000000000000000000000000000000000000000000000000000000810361465957608485604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152600f60448201527f41413935206f7574206f662067617300000000000000000000000000000000006064820152fd5b92935090917fdeadaa5100000000000000000000000000000000000000000000000000000000036146bc57506146a16146966146b1925a90612ead565b608084015190612e46565b6040830151836128548295614c2a565b905b5f8080806145b7565b9061472f9060405160208501518551907ff62676f440ff169a3a9afdbf812e89e7f95975ee8e5c31214ffdef631c5f4792602073ffffffffffffffffffffffffffffffffffffffff84511693015161471261349e565b9061472260405192839283612e2c565b0390a36040525a90612ead565b61473f6080840191825190612e46565b915f905a92855161010081015161012082015148018082105f1461488e5750955b61478d73ffffffffffffffffffffffffffffffffffffffff60e08401511693518203606084015190614b09565b01925f928061485f5750505173ffffffffffffffffffffffffffffffffffffffff16935b5a900301019283026040850151928184105f14614813575050806147e6575090816147e0929361285481614c2a565b906146b3565b807f4e487b7100000000000000000000000000000000000000000000000000000000602492526021600452fd5b614848908284939795039073ffffffffffffffffffffffffffffffffffffffff165f525f60205260405f209081540180915590565b506147e6575090825f61485a93614ba9565b6147e0565b9591905161486e575b506147b1565b935090506148875a9360a05f955a900391015190614b09565b905f614868565b905095614760565b5060205f803e5f516145cd565b614a0893506149dc916148e8917e42dc5300000000000000000000000000000000000000000000000000000000602086015261020060248601526102248501916131b6565b6149ab604484018860806101a091610120815173ffffffffffffffffffffffffffffffffffffffff8151168652602081015160208701526040810151604087015260608101516060870152838101518487015260a081015160a087015260c081015160c087015273ffffffffffffffffffffffffffffffffffffffff60e08201511660e087015261010081015161010087015201516101208501526020810151610140850152604081015161016085015260608101516101808501520151910152565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc8382030161020484015284612de9565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101885287612c2d565b60205f876145a2565b5081356143a1565b73ffffffffffffffffffffffffffffffffffffffff168015614aab575f80809381935af1614a45612eba565b5015614a4d57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f41413931206661696c65642073656e6420746f2062656e6566696369617279006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4141393020696e76616c69642062656e656669636961727900000000000000006044820152fd5b90619c408201811115614b2257606491600a9103020490565b50505f90565b9190917f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f6080602083015192519473ffffffffffffffffffffffffffffffffffffffff86511694602073ffffffffffffffffffffffffffffffffffffffff60e089015116970151916040519283525f602084015260408301526060820152a4565b9060807f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f91602084015193519573ffffffffffffffffffffffffffffffffffffffff87511695602073ffffffffffffffffffffffffffffffffffffffff60e08a015116980151926040519384521515602084015260408301526060820152a4565b60208101519051907f67b4fa9642f42120bf031f3051d1824b0fe25627945b27b8a6a65d5761d5482e60208073ffffffffffffffffffffffffffffffffffffffff855116940151604051908152a3565b90600211614cca57357fffffffffffffffffffffffffffffffffffffffff000000000000000000000000167f77020000000000000000000000000000000000000000000000000000000000001490565b505f90565b60ff8114614d2e5760ff811690601f8211614d065760405191614cf3604084612c2d565b6020808452838101919036833783525290565b7fb3512b0c000000000000000000000000000000000000000000000000000000005f5260045ffd5b506040515f6002548060011c9160018216918215614e3b575b602084108314614e0e578385528492908115614dd15750600114614d72575b612e4392500382612c2d565b5060025f90815290917f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace5b818310614db5575050906020612e4392820101614d66565b6020919350806001915483858801015201910190918392614d9d565b60209250612e439491507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001682840152151560051b820101614d66565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b92607f1692614d47565b60ff8114614e695760ff811690601f8211614d065760405191614cf3604084612c2d565b506040515f6003548060011c9160018216918215614f0b575b602084108314614e0e578385528492908115614dd15750600114614eac57612e4392500382612c2d565b5060035f90815290917fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b5b818310614eef575050906020612e4392820101614d66565b6020919350806001915483858801015201910190918392614ed7565b92607f1692614e82565b8015614fae575f60408051614f2981612c11565b828152826020820152015273ffffffffffffffffffffffffffffffffffffffff81169065ffffffffffff8160a01c16908115614fa0575b60409060d01c9165ffffffffffff825191614f7a83612c11565b8583528460208401521691829101524211908115614f9757509091565b90504211159091565b65ffffffffffff9150614f60565b505f905f90565b929190915f9080614fc8575b5050505050565b83519473ffffffffffffffffffffffffffffffffffffffff86511695614fee8386614c7a565b61535f5750853b6152fa576014821061529557604085510151602060405180927f570e1a36000000000000000000000000000000000000000000000000000000008252826004830152818781615048602482018a8d6131b6565b039273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690f190811561528a57849161526b575b5073ffffffffffffffffffffffffffffffffffffffff811680156152065787036151a1573b1561513c5750601411615139577fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d91604091503573ffffffffffffffffffffffffffffffffffffffff60e06020860151955101511673ffffffffffffffffffffffffffffffffffffffff83519260601c1682526020820152a35f80808080614fc1565b80fd5b608490604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152602060448201527f4141313520696e6974436f6465206d757374206372656174652073656e6465726064820152fd5b608482604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152602060448201527f4141313420696e6974436f6465206d7573742072657475726e2073656e6465726064820152fd5b608483604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601b60448201527f4141313320696e6974436f6465206661696c6564206f72204f4f4700000000006064820152fd5b615284915060203d602011611771576117638183612c2d565b5f615091565b6040513d86823e3d90fd5b608490604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601760448201527f4141393920696e6974436f646520746f6f20736d616c6c0000000000000000006064820152fd5b608490604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601f60448201527f414131302073656e64657220616c726561647920636f6e7374727563746564006064820152fd5b945050919050601482116153735750505050565b604073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169301519082601411612a3257833b15612a32575f809461542f96604051978896879586937fc09ad0d900000000000000000000000000000000000000000000000000000000855260048501526040602485015260147fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec60448601930191016131b6565b0393f1801561545557615445575b8080806145b7565b5f61544f91612c2d565b5f61543d565b6040513d5f823e3d90fd5b615478604092959493956060835260608301906133bd565b9460208201520152565b73ffffffffffffffffffffffffffffffffffffffff165f525f60205260405f2090815481811061381d5703905560019056fea2646970667358221220a2ee7c02d47f72772240d0dfa7174d99b6049a68ccdf3d4434c3918f6bd9c1e164736f6c634300081c0033" +} diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/deployments/ethereum/solcInputs/594e0595d5f1f4861d3b32a5f38cc32f.json b/dependencies/eth-infinitism-account-abstraction-0.8.0/deployments/ethereum/solcInputs/594e0595d5f1f4861d3b32a5f38cc32f.json new file mode 100644 index 00000000..fb28d1a3 --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/deployments/ethereum/solcInputs/594e0595d5f1f4861d3b32a5f38cc32f.json @@ -0,0 +1,120 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts/interfaces/IERC5267.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC5267.sol)\n\npragma solidity ^0.8.20;\n\ninterface IERC5267 {\n /**\n * @dev MAY be emitted to signal that the domain could have changed.\n */\n event EIP712DomainChanged();\n\n /**\n * @dev returns the fields and values that describe the domain separator used by this contract for EIP-712\n * signature.\n */\n function eip712Domain()\n external\n view\n returns (\n bytes1 fields,\n string memory name,\n string memory version,\n uint256 chainId,\n address verifyingContract,\n bytes32 salt,\n uint256[] memory extensions\n );\n}\n" + }, + "@openzeppelin/contracts/utils/cryptography/EIP712.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/cryptography/EIP712.sol)\n\npragma solidity ^0.8.20;\n\nimport {MessageHashUtils} from \"./MessageHashUtils.sol\";\nimport {ShortStrings, ShortString} from \"../ShortStrings.sol\";\nimport {IERC5267} from \"../../interfaces/IERC5267.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP-712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding scheme specified in the EIP requires a domain separator and a hash of the typed structured data, whose\n * encoding is very generic and therefore its implementation in Solidity is not feasible, thus this contract\n * does not implement the encoding itself. Protocols need to implement the type-specific encoding they need in order to\n * produce the hash of their typed data using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP-712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * NOTE: In the upgradeable version of this contract, the cached values will correspond to the address, and the domain\n * separator of the implementation contract. This will cause the {_domainSeparatorV4} function to always rebuild the\n * separator from the immutable values, which is cheaper than accessing a cached version in cold storage.\n *\n * @custom:oz-upgrades-unsafe-allow state-variable-immutable\n */\nabstract contract EIP712 is IERC5267 {\n using ShortStrings for *;\n\n bytes32 private constant TYPE_HASH =\n keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\");\n\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\n // invalidate the cached domain separator if the chain id changes.\n bytes32 private immutable _cachedDomainSeparator;\n uint256 private immutable _cachedChainId;\n address private immutable _cachedThis;\n\n bytes32 private immutable _hashedName;\n bytes32 private immutable _hashedVersion;\n\n ShortString private immutable _name;\n ShortString private immutable _version;\n string private _nameFallback;\n string private _versionFallback;\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP-712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n constructor(string memory name, string memory version) {\n _name = name.toShortStringWithFallback(_nameFallback);\n _version = version.toShortStringWithFallback(_versionFallback);\n _hashedName = keccak256(bytes(name));\n _hashedVersion = keccak256(bytes(version));\n\n _cachedChainId = block.chainid;\n _cachedDomainSeparator = _buildDomainSeparator();\n _cachedThis = address(this);\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view returns (bytes32) {\n if (address(this) == _cachedThis && block.chainid == _cachedChainId) {\n return _cachedDomainSeparator;\n } else {\n return _buildDomainSeparator();\n }\n }\n\n function _buildDomainSeparator() private view returns (bytes32) {\n return keccak256(abi.encode(TYPE_HASH, _hashedName, _hashedVersion, block.chainid, address(this)));\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return MessageHashUtils.toTypedDataHash(_domainSeparatorV4(), structHash);\n }\n\n /**\n * @dev See {IERC-5267}.\n */\n function eip712Domain()\n public\n view\n virtual\n returns (\n bytes1 fields,\n string memory name,\n string memory version,\n uint256 chainId,\n address verifyingContract,\n bytes32 salt,\n uint256[] memory extensions\n )\n {\n return (\n hex\"0f\", // 01111\n _EIP712Name(),\n _EIP712Version(),\n block.chainid,\n address(this),\n bytes32(0),\n new uint256[](0)\n );\n }\n\n /**\n * @dev The name parameter for the EIP712 domain.\n *\n * NOTE: By default this function reads _name which is an immutable value.\n * It only reads from storage if necessary (in case the value is too large to fit in a ShortString).\n */\n // solhint-disable-next-line func-name-mixedcase\n function _EIP712Name() internal view returns (string memory) {\n return _name.toStringWithFallback(_nameFallback);\n }\n\n /**\n * @dev The version parameter for the EIP712 domain.\n *\n * NOTE: By default this function reads _version which is an immutable value.\n * It only reads from storage if necessary (in case the value is too large to fit in a ShortString).\n */\n // solhint-disable-next-line func-name-mixedcase\n function _EIP712Version() internal view returns (string memory) {\n return _version.toStringWithFallback(_versionFallback);\n }\n}\n" + }, + "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/cryptography/MessageHashUtils.sol)\n\npragma solidity ^0.8.20;\n\nimport {Strings} from \"../Strings.sol\";\n\n/**\n * @dev Signature message hash utilities for producing digests to be consumed by {ECDSA} recovery or signing.\n *\n * The library provides methods for generating a hash of a message that conforms to the\n * https://eips.ethereum.org/EIPS/eip-191[ERC-191] and https://eips.ethereum.org/EIPS/eip-712[EIP 712]\n * specifications.\n */\nlibrary MessageHashUtils {\n /**\n * @dev Returns the keccak256 digest of an ERC-191 signed data with version\n * `0x45` (`personal_sign` messages).\n *\n * The digest is calculated by prefixing a bytes32 `messageHash` with\n * `\"\\x19Ethereum Signed Message:\\n32\"` and hashing the result. It corresponds with the\n * hash signed when using the https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] JSON-RPC method.\n *\n * NOTE: The `messageHash` parameter is intended to be the result of hashing a raw message with\n * keccak256, although any bytes32 value can be safely used because the final digest will\n * be re-hashed.\n *\n * See {ECDSA-recover}.\n */\n function toEthSignedMessageHash(bytes32 messageHash) internal pure returns (bytes32 digest) {\n assembly (\"memory-safe\") {\n mstore(0x00, \"\\x19Ethereum Signed Message:\\n32\") // 32 is the bytes-length of messageHash\n mstore(0x1c, messageHash) // 0x1c (28) is the length of the prefix\n digest := keccak256(0x00, 0x3c) // 0x3c is the length of the prefix (0x1c) + messageHash (0x20)\n }\n }\n\n /**\n * @dev Returns the keccak256 digest of an ERC-191 signed data with version\n * `0x45` (`personal_sign` messages).\n *\n * The digest is calculated by prefixing an arbitrary `message` with\n * `\"\\x19Ethereum Signed Message:\\n\" + len(message)` and hashing the result. It corresponds with the\n * hash signed when using the https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] JSON-RPC method.\n *\n * See {ECDSA-recover}.\n */\n function toEthSignedMessageHash(bytes memory message) internal pure returns (bytes32) {\n return\n keccak256(bytes.concat(\"\\x19Ethereum Signed Message:\\n\", bytes(Strings.toString(message.length)), message));\n }\n\n /**\n * @dev Returns the keccak256 digest of an ERC-191 signed data with version\n * `0x00` (data with intended validator).\n *\n * The digest is calculated by prefixing an arbitrary `data` with `\"\\x19\\x00\"` and the intended\n * `validator` address. Then hashing the result.\n *\n * See {ECDSA-recover}.\n */\n function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(hex\"19_00\", validator, data));\n }\n\n /**\n * @dev Returns the keccak256 digest of an EIP-712 typed data (ERC-191 version `0x01`).\n *\n * The digest is calculated from a `domainSeparator` and a `structHash`, by prefixing them with\n * `\\x19\\x01` and hashing the result. It corresponds to the hash signed by the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] JSON-RPC method as part of EIP-712.\n *\n * See {ECDSA-recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 digest) {\n assembly (\"memory-safe\") {\n let ptr := mload(0x40)\n mstore(ptr, hex\"19_01\")\n mstore(add(ptr, 0x02), domainSeparator)\n mstore(add(ptr, 0x22), structHash)\n digest := keccak256(ptr, 0x42)\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/introspection/ERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC165} from \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/introspection/IERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" + }, + "@openzeppelin/contracts/utils/math/Math.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.20;\n\nimport {Panic} from \"../Panic.sol\";\nimport {SafeCast} from \"./SafeCast.sol\";\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Floor, // Toward negative infinity\n Ceil, // Toward positive infinity\n Trunc, // Toward zero\n Expand // Away from zero\n }\n\n /**\n * @dev Returns the addition of two unsigned integers, with an success flag (no overflow).\n */\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n unchecked {\n uint256 c = a + b;\n if (c < a) return (false, 0);\n return (true, c);\n }\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, with an success flag (no overflow).\n */\n function trySub(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n unchecked {\n if (b > a) return (false, 0);\n return (true, a - b);\n }\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, with an success flag (no overflow).\n */\n function tryMul(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n unchecked {\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n // benefit is lost if 'b' is also tested.\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n if (a == 0) return (true, 0);\n uint256 c = a * b;\n if (c / a != b) return (false, 0);\n return (true, c);\n }\n }\n\n /**\n * @dev Returns the division of two unsigned integers, with a success flag (no division by zero).\n */\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n unchecked {\n if (b == 0) return (false, 0);\n return (true, a / b);\n }\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers, with a success flag (no division by zero).\n */\n function tryMod(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n unchecked {\n if (b == 0) return (false, 0);\n return (true, a % b);\n }\n }\n\n /**\n * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.\n *\n * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.\n * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute\n * one branch when needed, making this function more expensive.\n */\n function ternary(bool condition, uint256 a, uint256 b) internal pure returns (uint256) {\n unchecked {\n // branchless ternary works because:\n // b ^ (a ^ b) == a\n // b ^ 0 == b\n return b ^ ((a ^ b) * SafeCast.toUint(condition));\n }\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return ternary(a > b, a, b);\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return ternary(a < b, a, b);\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds towards infinity instead\n * of rounding towards zero.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n if (b == 0) {\n // Guarantee the same behavior as in a regular Solidity division.\n Panic.panic(Panic.DIVISION_BY_ZERO);\n }\n\n // The following calculation ensures accurate ceiling division without overflow.\n // Since a is non-zero, (a - 1) / b will not overflow.\n // The largest possible result occurs when (a - 1) / b is type(uint256).max,\n // but the largest value we can obtain is type(uint256).max - 1, which happens\n // when a = type(uint256).max and b = 1.\n unchecked {\n return SafeCast.toUint(a > 0) * ((a - 1) / b + 1);\n }\n }\n\n /**\n * @dev Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or\n * denominator == 0.\n *\n * Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by\n * Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2²⁵⁶ and mod 2²⁵⁶ - 1, then use\n // the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2²⁵⁶ + prod0.\n uint256 prod0 = x * y; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n // The surrounding unchecked block does not change this fact.\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2²⁵⁶. Also prevents denominator == 0.\n if (denominator <= prod1) {\n Panic.panic(ternary(denominator == 0, Panic.DIVISION_BY_ZERO, Panic.UNDER_OVERFLOW));\n }\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator.\n // Always >= 1. See https://cs.stackexchange.com/q/138556/92363.\n\n uint256 twos = denominator & (0 - denominator);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2²⁵⁶ / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2²⁵⁶. Now that denominator is an odd number, it has an inverse modulo 2²⁵⁶ such\n // that denominator * inv ≡ 1 mod 2²⁵⁶. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv ≡ 1 mod 2⁴.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also\n // works in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2⁸\n inverse *= 2 - denominator * inverse; // inverse mod 2¹⁶\n inverse *= 2 - denominator * inverse; // inverse mod 2³²\n inverse *= 2 - denominator * inverse; // inverse mod 2⁶⁴\n inverse *= 2 - denominator * inverse; // inverse mod 2¹²⁸\n inverse *= 2 - denominator * inverse; // inverse mod 2²⁵⁶\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2²⁵⁶. Since the preconditions guarantee that the outcome is\n // less than 2²⁵⁶, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @dev Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n return mulDiv(x, y, denominator) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0);\n }\n\n /**\n * @dev Calculate the modular multiplicative inverse of a number in Z/nZ.\n *\n * If n is a prime, then Z/nZ is a field. In that case all elements are inversible, except 0.\n * If n is not a prime, then Z/nZ is not a field, and some elements might not be inversible.\n *\n * If the input value is not inversible, 0 is returned.\n *\n * NOTE: If you know for sure that n is (big) a prime, it may be cheaper to use Fermat's little theorem and get the\n * inverse using `Math.modExp(a, n - 2, n)`. See {invModPrime}.\n */\n function invMod(uint256 a, uint256 n) internal pure returns (uint256) {\n unchecked {\n if (n == 0) return 0;\n\n // The inverse modulo is calculated using the Extended Euclidean Algorithm (iterative version)\n // Used to compute integers x and y such that: ax + ny = gcd(a, n).\n // When the gcd is 1, then the inverse of a modulo n exists and it's x.\n // ax + ny = 1\n // ax = 1 + (-y)n\n // ax ≡ 1 (mod n) # x is the inverse of a modulo n\n\n // If the remainder is 0 the gcd is n right away.\n uint256 remainder = a % n;\n uint256 gcd = n;\n\n // Therefore the initial coefficients are:\n // ax + ny = gcd(a, n) = n\n // 0a + 1n = n\n int256 x = 0;\n int256 y = 1;\n\n while (remainder != 0) {\n uint256 quotient = gcd / remainder;\n\n (gcd, remainder) = (\n // The old remainder is the next gcd to try.\n remainder,\n // Compute the next remainder.\n // Can't overflow given that (a % gcd) * (gcd // (a % gcd)) <= gcd\n // where gcd is at most n (capped to type(uint256).max)\n gcd - remainder * quotient\n );\n\n (x, y) = (\n // Increment the coefficient of a.\n y,\n // Decrement the coefficient of n.\n // Can overflow, but the result is casted to uint256 so that the\n // next value of y is \"wrapped around\" to a value between 0 and n - 1.\n x - y * int256(quotient)\n );\n }\n\n if (gcd != 1) return 0; // No inverse exists.\n return ternary(x < 0, n - uint256(-x), uint256(x)); // Wrap the result if it's negative.\n }\n }\n\n /**\n * @dev Variant of {invMod}. More efficient, but only works if `p` is known to be a prime greater than `2`.\n *\n * From https://en.wikipedia.org/wiki/Fermat%27s_little_theorem[Fermat's little theorem], we know that if p is\n * prime, then `a**(p-1) ≡ 1 mod p`. As a consequence, we have `a * a**(p-2) ≡ 1 mod p`, which means that\n * `a**(p-2)` is the modular multiplicative inverse of a in Fp.\n *\n * NOTE: this function does NOT check that `p` is a prime greater than `2`.\n */\n function invModPrime(uint256 a, uint256 p) internal view returns (uint256) {\n unchecked {\n return Math.modExp(a, p - 2, p);\n }\n }\n\n /**\n * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m)\n *\n * Requirements:\n * - modulus can't be zero\n * - underlying staticcall to precompile must succeed\n *\n * IMPORTANT: The result is only valid if the underlying call succeeds. When using this function, make\n * sure the chain you're using it on supports the precompiled contract for modular exponentiation\n * at address 0x05 as specified in https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise,\n * the underlying function will succeed given the lack of a revert, but the result may be incorrectly\n * interpreted as 0.\n */\n function modExp(uint256 b, uint256 e, uint256 m) internal view returns (uint256) {\n (bool success, uint256 result) = tryModExp(b, e, m);\n if (!success) {\n Panic.panic(Panic.DIVISION_BY_ZERO);\n }\n return result;\n }\n\n /**\n * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m).\n * It includes a success flag indicating if the operation succeeded. Operation will be marked as failed if trying\n * to operate modulo 0 or if the underlying precompile reverted.\n *\n * IMPORTANT: The result is only valid if the success flag is true. When using this function, make sure the chain\n * you're using it on supports the precompiled contract for modular exponentiation at address 0x05 as specified in\n * https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, the underlying function will succeed given the lack\n * of a revert, but the result may be incorrectly interpreted as 0.\n */\n function tryModExp(uint256 b, uint256 e, uint256 m) internal view returns (bool success, uint256 result) {\n if (m == 0) return (false, 0);\n assembly (\"memory-safe\") {\n let ptr := mload(0x40)\n // | Offset | Content | Content (Hex) |\n // |-----------|------------|--------------------------------------------------------------------|\n // | 0x00:0x1f | size of b | 0x0000000000000000000000000000000000000000000000000000000000000020 |\n // | 0x20:0x3f | size of e | 0x0000000000000000000000000000000000000000000000000000000000000020 |\n // | 0x40:0x5f | size of m | 0x0000000000000000000000000000000000000000000000000000000000000020 |\n // | 0x60:0x7f | value of b | 0x<.............................................................b> |\n // | 0x80:0x9f | value of e | 0x<.............................................................e> |\n // | 0xa0:0xbf | value of m | 0x<.............................................................m> |\n mstore(ptr, 0x20)\n mstore(add(ptr, 0x20), 0x20)\n mstore(add(ptr, 0x40), 0x20)\n mstore(add(ptr, 0x60), b)\n mstore(add(ptr, 0x80), e)\n mstore(add(ptr, 0xa0), m)\n\n // Given the result < m, it's guaranteed to fit in 32 bytes,\n // so we can use the memory scratch space located at offset 0.\n success := staticcall(gas(), 0x05, ptr, 0xc0, 0x00, 0x20)\n result := mload(0x00)\n }\n }\n\n /**\n * @dev Variant of {modExp} that supports inputs of arbitrary length.\n */\n function modExp(bytes memory b, bytes memory e, bytes memory m) internal view returns (bytes memory) {\n (bool success, bytes memory result) = tryModExp(b, e, m);\n if (!success) {\n Panic.panic(Panic.DIVISION_BY_ZERO);\n }\n return result;\n }\n\n /**\n * @dev Variant of {tryModExp} that supports inputs of arbitrary length.\n */\n function tryModExp(\n bytes memory b,\n bytes memory e,\n bytes memory m\n ) internal view returns (bool success, bytes memory result) {\n if (_zeroBytes(m)) return (false, new bytes(0));\n\n uint256 mLen = m.length;\n\n // Encode call args in result and move the free memory pointer\n result = abi.encodePacked(b.length, e.length, mLen, b, e, m);\n\n assembly (\"memory-safe\") {\n let dataPtr := add(result, 0x20)\n // Write result on top of args to avoid allocating extra memory.\n success := staticcall(gas(), 0x05, dataPtr, mload(result), dataPtr, mLen)\n // Overwrite the length.\n // result.length > returndatasize() is guaranteed because returndatasize() == m.length\n mstore(result, mLen)\n // Set the memory pointer after the returned data.\n mstore(0x40, add(dataPtr, mLen))\n }\n }\n\n /**\n * @dev Returns whether the provided byte array is zero.\n */\n function _zeroBytes(bytes memory byteArray) private pure returns (bool) {\n for (uint256 i = 0; i < byteArray.length; ++i) {\n if (byteArray[i] != 0) {\n return false;\n }\n }\n return true;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded\n * towards zero.\n *\n * This method is based on Newton's method for computing square roots; the algorithm is restricted to only\n * using integer operations.\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n unchecked {\n // Take care of easy edge cases when a == 0 or a == 1\n if (a <= 1) {\n return a;\n }\n\n // In this function, we use Newton's method to get a root of `f(x) := x² - a`. It involves building a\n // sequence x_n that converges toward sqrt(a). For each iteration x_n, we also define the error between\n // the current value as `ε_n = | x_n - sqrt(a) |`.\n //\n // For our first estimation, we consider `e` the smallest power of 2 which is bigger than the square root\n // of the target. (i.e. `2**(e-1) ≤ sqrt(a) < 2**e`). We know that `e ≤ 128` because `(2¹²⁸)² = 2²⁵⁶` is\n // bigger than any uint256.\n //\n // By noticing that\n // `2**(e-1) ≤ sqrt(a) < 2**e → (2**(e-1))² ≤ a < (2**e)² → 2**(2*e-2) ≤ a < 2**(2*e)`\n // we can deduce that `e - 1` is `log2(a) / 2`. We can thus compute `x_n = 2**(e-1)` using a method similar\n // to the msb function.\n uint256 aa = a;\n uint256 xn = 1;\n\n if (aa >= (1 << 128)) {\n aa >>= 128;\n xn <<= 64;\n }\n if (aa >= (1 << 64)) {\n aa >>= 64;\n xn <<= 32;\n }\n if (aa >= (1 << 32)) {\n aa >>= 32;\n xn <<= 16;\n }\n if (aa >= (1 << 16)) {\n aa >>= 16;\n xn <<= 8;\n }\n if (aa >= (1 << 8)) {\n aa >>= 8;\n xn <<= 4;\n }\n if (aa >= (1 << 4)) {\n aa >>= 4;\n xn <<= 2;\n }\n if (aa >= (1 << 2)) {\n xn <<= 1;\n }\n\n // We now have x_n such that `x_n = 2**(e-1) ≤ sqrt(a) < 2**e = 2 * x_n`. This implies ε_n ≤ 2**(e-1).\n //\n // We can refine our estimation by noticing that the middle of that interval minimizes the error.\n // If we move x_n to equal 2**(e-1) + 2**(e-2), then we reduce the error to ε_n ≤ 2**(e-2).\n // This is going to be our x_0 (and ε_0)\n xn = (3 * xn) >> 1; // ε_0 := | x_0 - sqrt(a) | ≤ 2**(e-2)\n\n // From here, Newton's method give us:\n // x_{n+1} = (x_n + a / x_n) / 2\n //\n // One should note that:\n // x_{n+1}² - a = ((x_n + a / x_n) / 2)² - a\n // = ((x_n² + a) / (2 * x_n))² - a\n // = (x_n⁴ + 2 * a * x_n² + a²) / (4 * x_n²) - a\n // = (x_n⁴ + 2 * a * x_n² + a² - 4 * a * x_n²) / (4 * x_n²)\n // = (x_n⁴ - 2 * a * x_n² + a²) / (4 * x_n²)\n // = (x_n² - a)² / (2 * x_n)²\n // = ((x_n² - a) / (2 * x_n))²\n // ≥ 0\n // Which proves that for all n ≥ 1, sqrt(a) ≤ x_n\n //\n // This gives us the proof of quadratic convergence of the sequence:\n // ε_{n+1} = | x_{n+1} - sqrt(a) |\n // = | (x_n + a / x_n) / 2 - sqrt(a) |\n // = | (x_n² + a - 2*x_n*sqrt(a)) / (2 * x_n) |\n // = | (x_n - sqrt(a))² / (2 * x_n) |\n // = | ε_n² / (2 * x_n) |\n // = ε_n² / | (2 * x_n) |\n //\n // For the first iteration, we have a special case where x_0 is known:\n // ε_1 = ε_0² / | (2 * x_0) |\n // ≤ (2**(e-2))² / (2 * (2**(e-1) + 2**(e-2)))\n // ≤ 2**(2*e-4) / (3 * 2**(e-1))\n // ≤ 2**(e-3) / 3\n // ≤ 2**(e-3-log2(3))\n // ≤ 2**(e-4.5)\n //\n // For the following iterations, we use the fact that, 2**(e-1) ≤ sqrt(a) ≤ x_n:\n // ε_{n+1} = ε_n² / | (2 * x_n) |\n // ≤ (2**(e-k))² / (2 * 2**(e-1))\n // ≤ 2**(2*e-2*k) / 2**e\n // ≤ 2**(e-2*k)\n xn = (xn + a / xn) >> 1; // ε_1 := | x_1 - sqrt(a) | ≤ 2**(e-4.5) -- special case, see above\n xn = (xn + a / xn) >> 1; // ε_2 := | x_2 - sqrt(a) | ≤ 2**(e-9) -- general case with k = 4.5\n xn = (xn + a / xn) >> 1; // ε_3 := | x_3 - sqrt(a) | ≤ 2**(e-18) -- general case with k = 9\n xn = (xn + a / xn) >> 1; // ε_4 := | x_4 - sqrt(a) | ≤ 2**(e-36) -- general case with k = 18\n xn = (xn + a / xn) >> 1; // ε_5 := | x_5 - sqrt(a) | ≤ 2**(e-72) -- general case with k = 36\n xn = (xn + a / xn) >> 1; // ε_6 := | x_6 - sqrt(a) | ≤ 2**(e-144) -- general case with k = 72\n\n // Because e ≤ 128 (as discussed during the first estimation phase), we know have reached a precision\n // ε_6 ≤ 2**(e-144) < 1. Given we're operating on integers, then we can ensure that xn is now either\n // sqrt(a) or sqrt(a) + 1.\n return xn - SafeCast.toUint(xn > a / xn);\n }\n }\n\n /**\n * @dev Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + SafeCast.toUint(unsignedRoundsUp(rounding) && result * result < a);\n }\n }\n\n /**\n * @dev Return the log in base 2 of a positive value rounded towards zero.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n uint256 exp;\n unchecked {\n exp = 128 * SafeCast.toUint(value > (1 << 128) - 1);\n value >>= exp;\n result += exp;\n\n exp = 64 * SafeCast.toUint(value > (1 << 64) - 1);\n value >>= exp;\n result += exp;\n\n exp = 32 * SafeCast.toUint(value > (1 << 32) - 1);\n value >>= exp;\n result += exp;\n\n exp = 16 * SafeCast.toUint(value > (1 << 16) - 1);\n value >>= exp;\n result += exp;\n\n exp = 8 * SafeCast.toUint(value > (1 << 8) - 1);\n value >>= exp;\n result += exp;\n\n exp = 4 * SafeCast.toUint(value > (1 << 4) - 1);\n value >>= exp;\n result += exp;\n\n exp = 2 * SafeCast.toUint(value > (1 << 2) - 1);\n value >>= exp;\n result += exp;\n\n result += SafeCast.toUint(value > 1);\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << result < value);\n }\n }\n\n /**\n * @dev Return the log in base 10 of a positive value rounded towards zero.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value >= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value >= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value >= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value >= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value >= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value >= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 10 ** result < value);\n }\n }\n\n /**\n * @dev Return the log in base 256 of a positive value rounded towards zero.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n uint256 isGt;\n unchecked {\n isGt = SafeCast.toUint(value > (1 << 128) - 1);\n value >>= isGt * 128;\n result += isGt * 16;\n\n isGt = SafeCast.toUint(value > (1 << 64) - 1);\n value >>= isGt * 64;\n result += isGt * 8;\n\n isGt = SafeCast.toUint(value > (1 << 32) - 1);\n value >>= isGt * 32;\n result += isGt * 4;\n\n isGt = SafeCast.toUint(value > (1 << 16) - 1);\n value >>= isGt * 16;\n result += isGt * 2;\n\n result += SafeCast.toUint(value > (1 << 8) - 1);\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << (result << 3) < value);\n }\n }\n\n /**\n * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.\n */\n function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {\n return uint8(rounding) % 2 == 1;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/math/SafeCast.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX/bool casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n */\nlibrary SafeCast {\n /**\n * @dev Value doesn't fit in an uint of `bits` size.\n */\n error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value);\n\n /**\n * @dev An int value doesn't fit in an uint of `bits` size.\n */\n error SafeCastOverflowedIntToUint(int256 value);\n\n /**\n * @dev Value doesn't fit in an int of `bits` size.\n */\n error SafeCastOverflowedIntDowncast(uint8 bits, int256 value);\n\n /**\n * @dev An uint value doesn't fit in an int of `bits` size.\n */\n error SafeCastOverflowedUintToInt(uint256 value);\n\n /**\n * @dev Returns the downcasted uint248 from uint256, reverting on\n * overflow (when the input is greater than largest uint248).\n *\n * Counterpart to Solidity's `uint248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n */\n function toUint248(uint256 value) internal pure returns (uint248) {\n if (value > type(uint248).max) {\n revert SafeCastOverflowedUintDowncast(248, value);\n }\n return uint248(value);\n }\n\n /**\n * @dev Returns the downcasted uint240 from uint256, reverting on\n * overflow (when the input is greater than largest uint240).\n *\n * Counterpart to Solidity's `uint240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n */\n function toUint240(uint256 value) internal pure returns (uint240) {\n if (value > type(uint240).max) {\n revert SafeCastOverflowedUintDowncast(240, value);\n }\n return uint240(value);\n }\n\n /**\n * @dev Returns the downcasted uint232 from uint256, reverting on\n * overflow (when the input is greater than largest uint232).\n *\n * Counterpart to Solidity's `uint232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n */\n function toUint232(uint256 value) internal pure returns (uint232) {\n if (value > type(uint232).max) {\n revert SafeCastOverflowedUintDowncast(232, value);\n }\n return uint232(value);\n }\n\n /**\n * @dev Returns the downcasted uint224 from uint256, reverting on\n * overflow (when the input is greater than largest uint224).\n *\n * Counterpart to Solidity's `uint224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n */\n function toUint224(uint256 value) internal pure returns (uint224) {\n if (value > type(uint224).max) {\n revert SafeCastOverflowedUintDowncast(224, value);\n }\n return uint224(value);\n }\n\n /**\n * @dev Returns the downcasted uint216 from uint256, reverting on\n * overflow (when the input is greater than largest uint216).\n *\n * Counterpart to Solidity's `uint216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n */\n function toUint216(uint256 value) internal pure returns (uint216) {\n if (value > type(uint216).max) {\n revert SafeCastOverflowedUintDowncast(216, value);\n }\n return uint216(value);\n }\n\n /**\n * @dev Returns the downcasted uint208 from uint256, reverting on\n * overflow (when the input is greater than largest uint208).\n *\n * Counterpart to Solidity's `uint208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n */\n function toUint208(uint256 value) internal pure returns (uint208) {\n if (value > type(uint208).max) {\n revert SafeCastOverflowedUintDowncast(208, value);\n }\n return uint208(value);\n }\n\n /**\n * @dev Returns the downcasted uint200 from uint256, reverting on\n * overflow (when the input is greater than largest uint200).\n *\n * Counterpart to Solidity's `uint200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n */\n function toUint200(uint256 value) internal pure returns (uint200) {\n if (value > type(uint200).max) {\n revert SafeCastOverflowedUintDowncast(200, value);\n }\n return uint200(value);\n }\n\n /**\n * @dev Returns the downcasted uint192 from uint256, reverting on\n * overflow (when the input is greater than largest uint192).\n *\n * Counterpart to Solidity's `uint192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n */\n function toUint192(uint256 value) internal pure returns (uint192) {\n if (value > type(uint192).max) {\n revert SafeCastOverflowedUintDowncast(192, value);\n }\n return uint192(value);\n }\n\n /**\n * @dev Returns the downcasted uint184 from uint256, reverting on\n * overflow (when the input is greater than largest uint184).\n *\n * Counterpart to Solidity's `uint184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n */\n function toUint184(uint256 value) internal pure returns (uint184) {\n if (value > type(uint184).max) {\n revert SafeCastOverflowedUintDowncast(184, value);\n }\n return uint184(value);\n }\n\n /**\n * @dev Returns the downcasted uint176 from uint256, reverting on\n * overflow (when the input is greater than largest uint176).\n *\n * Counterpart to Solidity's `uint176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n */\n function toUint176(uint256 value) internal pure returns (uint176) {\n if (value > type(uint176).max) {\n revert SafeCastOverflowedUintDowncast(176, value);\n }\n return uint176(value);\n }\n\n /**\n * @dev Returns the downcasted uint168 from uint256, reverting on\n * overflow (when the input is greater than largest uint168).\n *\n * Counterpart to Solidity's `uint168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n */\n function toUint168(uint256 value) internal pure returns (uint168) {\n if (value > type(uint168).max) {\n revert SafeCastOverflowedUintDowncast(168, value);\n }\n return uint168(value);\n }\n\n /**\n * @dev Returns the downcasted uint160 from uint256, reverting on\n * overflow (when the input is greater than largest uint160).\n *\n * Counterpart to Solidity's `uint160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n */\n function toUint160(uint256 value) internal pure returns (uint160) {\n if (value > type(uint160).max) {\n revert SafeCastOverflowedUintDowncast(160, value);\n }\n return uint160(value);\n }\n\n /**\n * @dev Returns the downcasted uint152 from uint256, reverting on\n * overflow (when the input is greater than largest uint152).\n *\n * Counterpart to Solidity's `uint152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n */\n function toUint152(uint256 value) internal pure returns (uint152) {\n if (value > type(uint152).max) {\n revert SafeCastOverflowedUintDowncast(152, value);\n }\n return uint152(value);\n }\n\n /**\n * @dev Returns the downcasted uint144 from uint256, reverting on\n * overflow (when the input is greater than largest uint144).\n *\n * Counterpart to Solidity's `uint144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n */\n function toUint144(uint256 value) internal pure returns (uint144) {\n if (value > type(uint144).max) {\n revert SafeCastOverflowedUintDowncast(144, value);\n }\n return uint144(value);\n }\n\n /**\n * @dev Returns the downcasted uint136 from uint256, reverting on\n * overflow (when the input is greater than largest uint136).\n *\n * Counterpart to Solidity's `uint136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n */\n function toUint136(uint256 value) internal pure returns (uint136) {\n if (value > type(uint136).max) {\n revert SafeCastOverflowedUintDowncast(136, value);\n }\n return uint136(value);\n }\n\n /**\n * @dev Returns the downcasted uint128 from uint256, reverting on\n * overflow (when the input is greater than largest uint128).\n *\n * Counterpart to Solidity's `uint128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n */\n function toUint128(uint256 value) internal pure returns (uint128) {\n if (value > type(uint128).max) {\n revert SafeCastOverflowedUintDowncast(128, value);\n }\n return uint128(value);\n }\n\n /**\n * @dev Returns the downcasted uint120 from uint256, reverting on\n * overflow (when the input is greater than largest uint120).\n *\n * Counterpart to Solidity's `uint120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n */\n function toUint120(uint256 value) internal pure returns (uint120) {\n if (value > type(uint120).max) {\n revert SafeCastOverflowedUintDowncast(120, value);\n }\n return uint120(value);\n }\n\n /**\n * @dev Returns the downcasted uint112 from uint256, reverting on\n * overflow (when the input is greater than largest uint112).\n *\n * Counterpart to Solidity's `uint112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n */\n function toUint112(uint256 value) internal pure returns (uint112) {\n if (value > type(uint112).max) {\n revert SafeCastOverflowedUintDowncast(112, value);\n }\n return uint112(value);\n }\n\n /**\n * @dev Returns the downcasted uint104 from uint256, reverting on\n * overflow (when the input is greater than largest uint104).\n *\n * Counterpart to Solidity's `uint104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n */\n function toUint104(uint256 value) internal pure returns (uint104) {\n if (value > type(uint104).max) {\n revert SafeCastOverflowedUintDowncast(104, value);\n }\n return uint104(value);\n }\n\n /**\n * @dev Returns the downcasted uint96 from uint256, reverting on\n * overflow (when the input is greater than largest uint96).\n *\n * Counterpart to Solidity's `uint96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n */\n function toUint96(uint256 value) internal pure returns (uint96) {\n if (value > type(uint96).max) {\n revert SafeCastOverflowedUintDowncast(96, value);\n }\n return uint96(value);\n }\n\n /**\n * @dev Returns the downcasted uint88 from uint256, reverting on\n * overflow (when the input is greater than largest uint88).\n *\n * Counterpart to Solidity's `uint88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n */\n function toUint88(uint256 value) internal pure returns (uint88) {\n if (value > type(uint88).max) {\n revert SafeCastOverflowedUintDowncast(88, value);\n }\n return uint88(value);\n }\n\n /**\n * @dev Returns the downcasted uint80 from uint256, reverting on\n * overflow (when the input is greater than largest uint80).\n *\n * Counterpart to Solidity's `uint80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n */\n function toUint80(uint256 value) internal pure returns (uint80) {\n if (value > type(uint80).max) {\n revert SafeCastOverflowedUintDowncast(80, value);\n }\n return uint80(value);\n }\n\n /**\n * @dev Returns the downcasted uint72 from uint256, reverting on\n * overflow (when the input is greater than largest uint72).\n *\n * Counterpart to Solidity's `uint72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n */\n function toUint72(uint256 value) internal pure returns (uint72) {\n if (value > type(uint72).max) {\n revert SafeCastOverflowedUintDowncast(72, value);\n }\n return uint72(value);\n }\n\n /**\n * @dev Returns the downcasted uint64 from uint256, reverting on\n * overflow (when the input is greater than largest uint64).\n *\n * Counterpart to Solidity's `uint64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n */\n function toUint64(uint256 value) internal pure returns (uint64) {\n if (value > type(uint64).max) {\n revert SafeCastOverflowedUintDowncast(64, value);\n }\n return uint64(value);\n }\n\n /**\n * @dev Returns the downcasted uint56 from uint256, reverting on\n * overflow (when the input is greater than largest uint56).\n *\n * Counterpart to Solidity's `uint56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n */\n function toUint56(uint256 value) internal pure returns (uint56) {\n if (value > type(uint56).max) {\n revert SafeCastOverflowedUintDowncast(56, value);\n }\n return uint56(value);\n }\n\n /**\n * @dev Returns the downcasted uint48 from uint256, reverting on\n * overflow (when the input is greater than largest uint48).\n *\n * Counterpart to Solidity's `uint48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n */\n function toUint48(uint256 value) internal pure returns (uint48) {\n if (value > type(uint48).max) {\n revert SafeCastOverflowedUintDowncast(48, value);\n }\n return uint48(value);\n }\n\n /**\n * @dev Returns the downcasted uint40 from uint256, reverting on\n * overflow (when the input is greater than largest uint40).\n *\n * Counterpart to Solidity's `uint40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n */\n function toUint40(uint256 value) internal pure returns (uint40) {\n if (value > type(uint40).max) {\n revert SafeCastOverflowedUintDowncast(40, value);\n }\n return uint40(value);\n }\n\n /**\n * @dev Returns the downcasted uint32 from uint256, reverting on\n * overflow (when the input is greater than largest uint32).\n *\n * Counterpart to Solidity's `uint32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n */\n function toUint32(uint256 value) internal pure returns (uint32) {\n if (value > type(uint32).max) {\n revert SafeCastOverflowedUintDowncast(32, value);\n }\n return uint32(value);\n }\n\n /**\n * @dev Returns the downcasted uint24 from uint256, reverting on\n * overflow (when the input is greater than largest uint24).\n *\n * Counterpart to Solidity's `uint24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n */\n function toUint24(uint256 value) internal pure returns (uint24) {\n if (value > type(uint24).max) {\n revert SafeCastOverflowedUintDowncast(24, value);\n }\n return uint24(value);\n }\n\n /**\n * @dev Returns the downcasted uint16 from uint256, reverting on\n * overflow (when the input is greater than largest uint16).\n *\n * Counterpart to Solidity's `uint16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n */\n function toUint16(uint256 value) internal pure returns (uint16) {\n if (value > type(uint16).max) {\n revert SafeCastOverflowedUintDowncast(16, value);\n }\n return uint16(value);\n }\n\n /**\n * @dev Returns the downcasted uint8 from uint256, reverting on\n * overflow (when the input is greater than largest uint8).\n *\n * Counterpart to Solidity's `uint8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n */\n function toUint8(uint256 value) internal pure returns (uint8) {\n if (value > type(uint8).max) {\n revert SafeCastOverflowedUintDowncast(8, value);\n }\n return uint8(value);\n }\n\n /**\n * @dev Converts a signed int256 into an unsigned uint256.\n *\n * Requirements:\n *\n * - input must be greater than or equal to 0.\n */\n function toUint256(int256 value) internal pure returns (uint256) {\n if (value < 0) {\n revert SafeCastOverflowedIntToUint(value);\n }\n return uint256(value);\n }\n\n /**\n * @dev Returns the downcasted int248 from int256, reverting on\n * overflow (when the input is less than smallest int248 or\n * greater than largest int248).\n *\n * Counterpart to Solidity's `int248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n */\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\n downcasted = int248(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(248, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int240 from int256, reverting on\n * overflow (when the input is less than smallest int240 or\n * greater than largest int240).\n *\n * Counterpart to Solidity's `int240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n */\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\n downcasted = int240(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(240, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int232 from int256, reverting on\n * overflow (when the input is less than smallest int232 or\n * greater than largest int232).\n *\n * Counterpart to Solidity's `int232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n */\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\n downcasted = int232(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(232, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int224 from int256, reverting on\n * overflow (when the input is less than smallest int224 or\n * greater than largest int224).\n *\n * Counterpart to Solidity's `int224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n */\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\n downcasted = int224(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(224, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int216 from int256, reverting on\n * overflow (when the input is less than smallest int216 or\n * greater than largest int216).\n *\n * Counterpart to Solidity's `int216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n */\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\n downcasted = int216(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(216, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int208 from int256, reverting on\n * overflow (when the input is less than smallest int208 or\n * greater than largest int208).\n *\n * Counterpart to Solidity's `int208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n */\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\n downcasted = int208(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(208, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int200 from int256, reverting on\n * overflow (when the input is less than smallest int200 or\n * greater than largest int200).\n *\n * Counterpart to Solidity's `int200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n */\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\n downcasted = int200(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(200, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int192 from int256, reverting on\n * overflow (when the input is less than smallest int192 or\n * greater than largest int192).\n *\n * Counterpart to Solidity's `int192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n */\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\n downcasted = int192(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(192, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int184 from int256, reverting on\n * overflow (when the input is less than smallest int184 or\n * greater than largest int184).\n *\n * Counterpart to Solidity's `int184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n */\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\n downcasted = int184(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(184, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int176 from int256, reverting on\n * overflow (when the input is less than smallest int176 or\n * greater than largest int176).\n *\n * Counterpart to Solidity's `int176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n */\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\n downcasted = int176(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(176, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int168 from int256, reverting on\n * overflow (when the input is less than smallest int168 or\n * greater than largest int168).\n *\n * Counterpart to Solidity's `int168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n */\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\n downcasted = int168(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(168, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int160 from int256, reverting on\n * overflow (when the input is less than smallest int160 or\n * greater than largest int160).\n *\n * Counterpart to Solidity's `int160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n */\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\n downcasted = int160(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(160, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int152 from int256, reverting on\n * overflow (when the input is less than smallest int152 or\n * greater than largest int152).\n *\n * Counterpart to Solidity's `int152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n */\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\n downcasted = int152(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(152, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int144 from int256, reverting on\n * overflow (when the input is less than smallest int144 or\n * greater than largest int144).\n *\n * Counterpart to Solidity's `int144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n */\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\n downcasted = int144(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(144, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int136 from int256, reverting on\n * overflow (when the input is less than smallest int136 or\n * greater than largest int136).\n *\n * Counterpart to Solidity's `int136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n */\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\n downcasted = int136(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(136, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int128 from int256, reverting on\n * overflow (when the input is less than smallest int128 or\n * greater than largest int128).\n *\n * Counterpart to Solidity's `int128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n */\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\n downcasted = int128(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(128, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int120 from int256, reverting on\n * overflow (when the input is less than smallest int120 or\n * greater than largest int120).\n *\n * Counterpart to Solidity's `int120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n */\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\n downcasted = int120(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(120, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int112 from int256, reverting on\n * overflow (when the input is less than smallest int112 or\n * greater than largest int112).\n *\n * Counterpart to Solidity's `int112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n */\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\n downcasted = int112(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(112, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int104 from int256, reverting on\n * overflow (when the input is less than smallest int104 or\n * greater than largest int104).\n *\n * Counterpart to Solidity's `int104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n */\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\n downcasted = int104(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(104, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int96 from int256, reverting on\n * overflow (when the input is less than smallest int96 or\n * greater than largest int96).\n *\n * Counterpart to Solidity's `int96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n */\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\n downcasted = int96(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(96, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int88 from int256, reverting on\n * overflow (when the input is less than smallest int88 or\n * greater than largest int88).\n *\n * Counterpart to Solidity's `int88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n */\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\n downcasted = int88(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(88, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int80 from int256, reverting on\n * overflow (when the input is less than smallest int80 or\n * greater than largest int80).\n *\n * Counterpart to Solidity's `int80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n */\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\n downcasted = int80(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(80, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int72 from int256, reverting on\n * overflow (when the input is less than smallest int72 or\n * greater than largest int72).\n *\n * Counterpart to Solidity's `int72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n */\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\n downcasted = int72(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(72, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int64 from int256, reverting on\n * overflow (when the input is less than smallest int64 or\n * greater than largest int64).\n *\n * Counterpart to Solidity's `int64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n */\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\n downcasted = int64(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(64, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int56 from int256, reverting on\n * overflow (when the input is less than smallest int56 or\n * greater than largest int56).\n *\n * Counterpart to Solidity's `int56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n */\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\n downcasted = int56(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(56, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int48 from int256, reverting on\n * overflow (when the input is less than smallest int48 or\n * greater than largest int48).\n *\n * Counterpart to Solidity's `int48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n */\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\n downcasted = int48(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(48, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int40 from int256, reverting on\n * overflow (when the input is less than smallest int40 or\n * greater than largest int40).\n *\n * Counterpart to Solidity's `int40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n */\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\n downcasted = int40(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(40, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int32 from int256, reverting on\n * overflow (when the input is less than smallest int32 or\n * greater than largest int32).\n *\n * Counterpart to Solidity's `int32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n */\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\n downcasted = int32(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(32, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int24 from int256, reverting on\n * overflow (when the input is less than smallest int24 or\n * greater than largest int24).\n *\n * Counterpart to Solidity's `int24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n */\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\n downcasted = int24(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(24, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int16 from int256, reverting on\n * overflow (when the input is less than smallest int16 or\n * greater than largest int16).\n *\n * Counterpart to Solidity's `int16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n */\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\n downcasted = int16(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(16, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int8 from int256, reverting on\n * overflow (when the input is less than smallest int8 or\n * greater than largest int8).\n *\n * Counterpart to Solidity's `int8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n */\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\n downcasted = int8(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(8, value);\n }\n }\n\n /**\n * @dev Converts an unsigned uint256 into a signed int256.\n *\n * Requirements:\n *\n * - input must be less than or equal to maxInt256.\n */\n function toInt256(uint256 value) internal pure returns (int256) {\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n if (value > uint256(type(int256).max)) {\n revert SafeCastOverflowedUintToInt(value);\n }\n return int256(value);\n }\n\n /**\n * @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump.\n */\n function toUint(bool b) internal pure returns (uint256 u) {\n assembly (\"memory-safe\") {\n u := iszero(iszero(b))\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/math/SignedMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.20;\n\nimport {SafeCast} from \"./SafeCast.sol\";\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.\n *\n * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.\n * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute\n * one branch when needed, making this function more expensive.\n */\n function ternary(bool condition, int256 a, int256 b) internal pure returns (int256) {\n unchecked {\n // branchless ternary works because:\n // b ^ (a ^ b) == a\n // b ^ 0 == b\n return b ^ ((a ^ b) * int256(SafeCast.toUint(condition)));\n }\n }\n\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return ternary(a > b, a, b);\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return ternary(a < b, a, b);\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a & b) + ((a ^ b) >> 1);\n return x + (int256(uint256(x) >> 255) & (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // Formula from the \"Bit Twiddling Hacks\" by Sean Eron Anderson.\n // Since `n` is a signed integer, the generated bytecode will use the SAR opcode to perform the right shift,\n // taking advantage of the most significant (or \"sign\" bit) in two's complement representation.\n // This opcode adds new most significant bits set to the value of the previous most significant bit. As a result,\n // the mask will either be `bytes32(0)` (if n is positive) or `~bytes32(0)` (if n is negative).\n int256 mask = n >> 255;\n\n // A `bytes32(0)` mask leaves the input unchanged, while a `~bytes32(0)` mask complements it.\n return uint256((n + mask) ^ mask);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Panic.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/Panic.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Helper library for emitting standardized panic codes.\n *\n * ```solidity\n * contract Example {\n * using Panic for uint256;\n *\n * // Use any of the declared internal constants\n * function foo() { Panic.GENERIC.panic(); }\n *\n * // Alternatively\n * function foo() { Panic.panic(Panic.GENERIC); }\n * }\n * ```\n *\n * Follows the list from https://github.com/ethereum/solidity/blob/v0.8.24/libsolutil/ErrorCodes.h[libsolutil].\n *\n * _Available since v5.1._\n */\n// slither-disable-next-line unused-state\nlibrary Panic {\n /// @dev generic / unspecified error\n uint256 internal constant GENERIC = 0x00;\n /// @dev used by the assert() builtin\n uint256 internal constant ASSERT = 0x01;\n /// @dev arithmetic underflow or overflow\n uint256 internal constant UNDER_OVERFLOW = 0x11;\n /// @dev division or modulo by zero\n uint256 internal constant DIVISION_BY_ZERO = 0x12;\n /// @dev enum conversion error\n uint256 internal constant ENUM_CONVERSION_ERROR = 0x21;\n /// @dev invalid encoding in storage\n uint256 internal constant STORAGE_ENCODING_ERROR = 0x22;\n /// @dev empty array pop\n uint256 internal constant EMPTY_ARRAY_POP = 0x31;\n /// @dev array out of bounds access\n uint256 internal constant ARRAY_OUT_OF_BOUNDS = 0x32;\n /// @dev resource error (too large allocation or too large array)\n uint256 internal constant RESOURCE_ERROR = 0x41;\n /// @dev calling invalid internal function\n uint256 internal constant INVALID_INTERNAL_FUNCTION = 0x51;\n\n /// @dev Reverts with a panic code. Recommended to use with\n /// the internal constants with predefined codes.\n function panic(uint256 code) internal pure {\n assembly (\"memory-safe\") {\n mstore(0x00, 0x4e487b71)\n mstore(0x20, code)\n revert(0x1c, 0x24)\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/ReentrancyGuardTransient.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/ReentrancyGuardTransient.sol)\n\npragma solidity ^0.8.24;\n\nimport {TransientSlot} from \"./TransientSlot.sol\";\n\n/**\n * @dev Variant of {ReentrancyGuard} that uses transient storage.\n *\n * NOTE: This variant only works on networks where EIP-1153 is available.\n *\n * _Available since v5.1._\n */\nabstract contract ReentrancyGuardTransient {\n using TransientSlot for *;\n\n // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.ReentrancyGuard\")) - 1)) & ~bytes32(uint256(0xff))\n bytes32 private constant REENTRANCY_GUARD_STORAGE =\n 0x9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00;\n\n /**\n * @dev Unauthorized reentrant call.\n */\n error ReentrancyGuardReentrantCall();\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and making it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n _nonReentrantBefore();\n _;\n _nonReentrantAfter();\n }\n\n function _nonReentrantBefore() private {\n // On the first call to nonReentrant, _status will be NOT_ENTERED\n if (_reentrancyGuardEntered()) {\n revert ReentrancyGuardReentrantCall();\n }\n\n // Any calls to nonReentrant after this point will fail\n REENTRANCY_GUARD_STORAGE.asBoolean().tstore(true);\n }\n\n function _nonReentrantAfter() private {\n REENTRANCY_GUARD_STORAGE.asBoolean().tstore(false);\n }\n\n /**\n * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n * `nonReentrant` function in the call stack.\n */\n function _reentrancyGuardEntered() internal view returns (bool) {\n return REENTRANCY_GUARD_STORAGE.asBoolean().tload();\n }\n}\n" + }, + "@openzeppelin/contracts/utils/ShortStrings.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/ShortStrings.sol)\n\npragma solidity ^0.8.20;\n\nimport {StorageSlot} from \"./StorageSlot.sol\";\n\n// | string | 0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA |\n// | length | 0x BB |\ntype ShortString is bytes32;\n\n/**\n * @dev This library provides functions to convert short memory strings\n * into a `ShortString` type that can be used as an immutable variable.\n *\n * Strings of arbitrary length can be optimized using this library if\n * they are short enough (up to 31 bytes) by packing them with their\n * length (1 byte) in a single EVM word (32 bytes). Additionally, a\n * fallback mechanism can be used for every other case.\n *\n * Usage example:\n *\n * ```solidity\n * contract Named {\n * using ShortStrings for *;\n *\n * ShortString private immutable _name;\n * string private _nameFallback;\n *\n * constructor(string memory contractName) {\n * _name = contractName.toShortStringWithFallback(_nameFallback);\n * }\n *\n * function name() external view returns (string memory) {\n * return _name.toStringWithFallback(_nameFallback);\n * }\n * }\n * ```\n */\nlibrary ShortStrings {\n // Used as an identifier for strings longer than 31 bytes.\n bytes32 private constant FALLBACK_SENTINEL = 0x00000000000000000000000000000000000000000000000000000000000000FF;\n\n error StringTooLong(string str);\n error InvalidShortString();\n\n /**\n * @dev Encode a string of at most 31 chars into a `ShortString`.\n *\n * This will trigger a `StringTooLong` error is the input string is too long.\n */\n function toShortString(string memory str) internal pure returns (ShortString) {\n bytes memory bstr = bytes(str);\n if (bstr.length > 31) {\n revert StringTooLong(str);\n }\n return ShortString.wrap(bytes32(uint256(bytes32(bstr)) | bstr.length));\n }\n\n /**\n * @dev Decode a `ShortString` back to a \"normal\" string.\n */\n function toString(ShortString sstr) internal pure returns (string memory) {\n uint256 len = byteLength(sstr);\n // using `new string(len)` would work locally but is not memory safe.\n string memory str = new string(32);\n assembly (\"memory-safe\") {\n mstore(str, len)\n mstore(add(str, 0x20), sstr)\n }\n return str;\n }\n\n /**\n * @dev Return the length of a `ShortString`.\n */\n function byteLength(ShortString sstr) internal pure returns (uint256) {\n uint256 result = uint256(ShortString.unwrap(sstr)) & 0xFF;\n if (result > 31) {\n revert InvalidShortString();\n }\n return result;\n }\n\n /**\n * @dev Encode a string into a `ShortString`, or write it to storage if it is too long.\n */\n function toShortStringWithFallback(string memory value, string storage store) internal returns (ShortString) {\n if (bytes(value).length < 32) {\n return toShortString(value);\n } else {\n StorageSlot.getStringSlot(store).value = value;\n return ShortString.wrap(FALLBACK_SENTINEL);\n }\n }\n\n /**\n * @dev Decode a string that was encoded to `ShortString` or written to storage using {setWithFallback}.\n */\n function toStringWithFallback(ShortString value, string storage store) internal pure returns (string memory) {\n if (ShortString.unwrap(value) != FALLBACK_SENTINEL) {\n return toString(value);\n } else {\n return store;\n }\n }\n\n /**\n * @dev Return the length of a string that was encoded to `ShortString` or written to storage using\n * {setWithFallback}.\n *\n * WARNING: This will return the \"byte length\" of the string. This may not reflect the actual length in terms of\n * actual characters as the UTF-8 encoding of a single character can span over multiple bytes.\n */\n function byteLengthWithFallback(ShortString value, string storage store) internal view returns (uint256) {\n if (ShortString.unwrap(value) != FALLBACK_SENTINEL) {\n return byteLength(value);\n } else {\n return bytes(store).length;\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/StorageSlot.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/StorageSlot.sol)\n// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Library for reading and writing primitive types to specific storage slots.\n *\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\n * This library helps with reading and writing to such slots without the need for inline assembly.\n *\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\n *\n * Example usage to set ERC-1967 implementation slot:\n * ```solidity\n * contract ERC1967 {\n * // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.\n * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n *\n * function _getImplementation() internal view returns (address) {\n * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n * }\n *\n * function _setImplementation(address newImplementation) internal {\n * require(newImplementation.code.length > 0);\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n * }\n * }\n * ```\n *\n * TIP: Consider using this library along with {SlotDerivation}.\n */\nlibrary StorageSlot {\n struct AddressSlot {\n address value;\n }\n\n struct BooleanSlot {\n bool value;\n }\n\n struct Bytes32Slot {\n bytes32 value;\n }\n\n struct Uint256Slot {\n uint256 value;\n }\n\n struct Int256Slot {\n int256 value;\n }\n\n struct StringSlot {\n string value;\n }\n\n struct BytesSlot {\n bytes value;\n }\n\n /**\n * @dev Returns an `AddressSlot` with member `value` located at `slot`.\n */\n function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\n assembly (\"memory-safe\") {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns a `BooleanSlot` with member `value` located at `slot`.\n */\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\n assembly (\"memory-safe\") {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns a `Bytes32Slot` with member `value` located at `slot`.\n */\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\n assembly (\"memory-safe\") {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns a `Uint256Slot` with member `value` located at `slot`.\n */\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\n assembly (\"memory-safe\") {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns a `Int256Slot` with member `value` located at `slot`.\n */\n function getInt256Slot(bytes32 slot) internal pure returns (Int256Slot storage r) {\n assembly (\"memory-safe\") {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns a `StringSlot` with member `value` located at `slot`.\n */\n function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {\n assembly (\"memory-safe\") {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `StringSlot` representation of the string storage pointer `store`.\n */\n function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {\n assembly (\"memory-safe\") {\n r.slot := store.slot\n }\n }\n\n /**\n * @dev Returns a `BytesSlot` with member `value` located at `slot`.\n */\n function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {\n assembly (\"memory-safe\") {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.\n */\n function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {\n assembly (\"memory-safe\") {\n r.slot := store.slot\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Strings.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/Strings.sol)\n\npragma solidity ^0.8.20;\n\nimport {Math} from \"./math/Math.sol\";\nimport {SignedMath} from \"./math/SignedMath.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant HEX_DIGITS = \"0123456789abcdef\";\n uint8 private constant ADDRESS_LENGTH = 20;\n\n /**\n * @dev The `value` string doesn't fit in the specified `length`.\n */\n error StringsInsufficientHexLength(uint256 value, uint256 length);\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n assembly (\"memory-safe\") {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n assembly (\"memory-safe\") {\n mstore8(ptr, byte(mod(value, 10), HEX_DIGITS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toStringSigned(int256 value) internal pure returns (string memory) {\n return string.concat(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value)));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n uint256 localValue = value;\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = HEX_DIGITS[localValue & 0xf];\n localValue >>= 4;\n }\n if (localValue != 0) {\n revert StringsInsufficientHexLength(value, length);\n }\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal\n * representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its checksummed ASCII `string` hexadecimal\n * representation, according to EIP-55.\n */\n function toChecksumHexString(address addr) internal pure returns (string memory) {\n bytes memory buffer = bytes(toHexString(addr));\n\n // hash the hex part of buffer (skip length + 2 bytes, length 40)\n uint256 hashValue;\n assembly (\"memory-safe\") {\n hashValue := shr(96, keccak256(add(buffer, 0x22), 40))\n }\n\n for (uint256 i = 41; i > 1; --i) {\n // possible values for buffer[i] are 48 (0) to 57 (9) and 97 (a) to 102 (f)\n if (hashValue & 0xf > 7 && uint8(buffer[i]) > 96) {\n // case shift by xoring with 0x20\n buffer[i] ^= 0x20;\n }\n hashValue >>= 4;\n }\n return string(buffer);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n" + }, + "@openzeppelin/contracts/utils/TransientSlot.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/TransientSlot.sol)\n// This file was procedurally generated from scripts/generate/templates/TransientSlot.js.\n\npragma solidity ^0.8.24;\n\n/**\n * @dev Library for reading and writing value-types to specific transient storage slots.\n *\n * Transient slots are often used to store temporary values that are removed after the current transaction.\n * This library helps with reading and writing to such slots without the need for inline assembly.\n *\n * * Example reading and writing values using transient storage:\n * ```solidity\n * contract Lock {\n * using TransientSlot for *;\n *\n * // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.\n * bytes32 internal constant _LOCK_SLOT = 0xf4678858b2b588224636b8522b729e7722d32fc491da849ed75b3fdf3c84f542;\n *\n * modifier locked() {\n * require(!_LOCK_SLOT.asBoolean().tload());\n *\n * _LOCK_SLOT.asBoolean().tstore(true);\n * _;\n * _LOCK_SLOT.asBoolean().tstore(false);\n * }\n * }\n * ```\n *\n * TIP: Consider using this library along with {SlotDerivation}.\n */\nlibrary TransientSlot {\n /**\n * @dev UDVT that represent a slot holding a address.\n */\n type AddressSlot is bytes32;\n\n /**\n * @dev Cast an arbitrary slot to a AddressSlot.\n */\n function asAddress(bytes32 slot) internal pure returns (AddressSlot) {\n return AddressSlot.wrap(slot);\n }\n\n /**\n * @dev UDVT that represent a slot holding a bool.\n */\n type BooleanSlot is bytes32;\n\n /**\n * @dev Cast an arbitrary slot to a BooleanSlot.\n */\n function asBoolean(bytes32 slot) internal pure returns (BooleanSlot) {\n return BooleanSlot.wrap(slot);\n }\n\n /**\n * @dev UDVT that represent a slot holding a bytes32.\n */\n type Bytes32Slot is bytes32;\n\n /**\n * @dev Cast an arbitrary slot to a Bytes32Slot.\n */\n function asBytes32(bytes32 slot) internal pure returns (Bytes32Slot) {\n return Bytes32Slot.wrap(slot);\n }\n\n /**\n * @dev UDVT that represent a slot holding a uint256.\n */\n type Uint256Slot is bytes32;\n\n /**\n * @dev Cast an arbitrary slot to a Uint256Slot.\n */\n function asUint256(bytes32 slot) internal pure returns (Uint256Slot) {\n return Uint256Slot.wrap(slot);\n }\n\n /**\n * @dev UDVT that represent a slot holding a int256.\n */\n type Int256Slot is bytes32;\n\n /**\n * @dev Cast an arbitrary slot to a Int256Slot.\n */\n function asInt256(bytes32 slot) internal pure returns (Int256Slot) {\n return Int256Slot.wrap(slot);\n }\n\n /**\n * @dev Load the value held at location `slot` in transient storage.\n */\n function tload(AddressSlot slot) internal view returns (address value) {\n assembly (\"memory-safe\") {\n value := tload(slot)\n }\n }\n\n /**\n * @dev Store `value` at location `slot` in transient storage.\n */\n function tstore(AddressSlot slot, address value) internal {\n assembly (\"memory-safe\") {\n tstore(slot, value)\n }\n }\n\n /**\n * @dev Load the value held at location `slot` in transient storage.\n */\n function tload(BooleanSlot slot) internal view returns (bool value) {\n assembly (\"memory-safe\") {\n value := tload(slot)\n }\n }\n\n /**\n * @dev Store `value` at location `slot` in transient storage.\n */\n function tstore(BooleanSlot slot, bool value) internal {\n assembly (\"memory-safe\") {\n tstore(slot, value)\n }\n }\n\n /**\n * @dev Load the value held at location `slot` in transient storage.\n */\n function tload(Bytes32Slot slot) internal view returns (bytes32 value) {\n assembly (\"memory-safe\") {\n value := tload(slot)\n }\n }\n\n /**\n * @dev Store `value` at location `slot` in transient storage.\n */\n function tstore(Bytes32Slot slot, bytes32 value) internal {\n assembly (\"memory-safe\") {\n tstore(slot, value)\n }\n }\n\n /**\n * @dev Load the value held at location `slot` in transient storage.\n */\n function tload(Uint256Slot slot) internal view returns (uint256 value) {\n assembly (\"memory-safe\") {\n value := tload(slot)\n }\n }\n\n /**\n * @dev Store `value` at location `slot` in transient storage.\n */\n function tstore(Uint256Slot slot, uint256 value) internal {\n assembly (\"memory-safe\") {\n tstore(slot, value)\n }\n }\n\n /**\n * @dev Load the value held at location `slot` in transient storage.\n */\n function tload(Int256Slot slot) internal view returns (int256 value) {\n assembly (\"memory-safe\") {\n value := tload(slot)\n }\n }\n\n /**\n * @dev Store `value` at location `slot` in transient storage.\n */\n function tstore(Int256Slot slot, int256 value) internal {\n assembly (\"memory-safe\") {\n tstore(slot, value)\n }\n }\n}\n" + }, + "contracts/core/Eip7702Support.sol": { + "content": "pragma solidity ^0.8.28;\n// SPDX-License-Identifier: MIT\n// solhint-disable no-inline-assembly\n\nimport \"../interfaces/PackedUserOperation.sol\";\nimport \"../core/UserOperationLib.sol\";\n\nlibrary Eip7702Support {\n\n // EIP-7702 code prefix before delegate address.\n bytes3 internal constant EIP7702_PREFIX = 0xef0100;\n\n // EIP-7702 initCode marker, to specify this account is EIP-7702.\n bytes2 internal constant INITCODE_EIP7702_MARKER = 0x7702;\n\n using UserOperationLib for PackedUserOperation;\n\n /**\n * Get the alternative 'InitCodeHash' value for the UserOp hash calculation when using EIP-7702.\n *\n * @param userOp - the UserOperation to for the 'InitCodeHash' calculation.\n * @return the 'InitCodeHash' value.\n */\n function _getEip7702InitCodeHashOverride(PackedUserOperation calldata userOp) internal view returns (bytes32) {\n bytes calldata initCode = userOp.initCode;\n if (!_isEip7702InitCode(initCode)) {\n return 0;\n }\n address delegate = _getEip7702Delegate(userOp.sender);\n if (initCode.length <= 20)\n return keccak256(abi.encodePacked(delegate));\n else\n return keccak256(abi.encodePacked(delegate, initCode[20 :]));\n }\n\n /**\n * Check if this 'initCode' is actually an EIP-7702 authorization.\n * This is indicated by 'initCode' that starts with INITCODE_EIP7702_MARKER.\n *\n * @param initCode - the 'initCode' to check.\n * @return true if the 'initCode' is EIP-7702 authorization, false otherwise.\n */\n function _isEip7702InitCode(bytes calldata initCode) internal pure returns (bool) {\n\n if (initCode.length < 2) {\n return false;\n }\n bytes20 initCodeStart;\n // non-empty calldata bytes are always zero-padded to 32-bytes, so can be safely casted to \"bytes20\"\n assembly (\"memory-safe\") {\n initCodeStart := calldataload(initCode.offset)\n }\n // make sure first 20 bytes of initCode are \"0x7702\" (padded with zeros)\n return initCodeStart == bytes20(INITCODE_EIP7702_MARKER);\n }\n\n /**\n * Get the EIP-7702 delegate from contract code.\n * Must only be used if _isEip7702InitCode(initCode) is true.\n *\n * @param sender - the EIP-7702 'sender' account to get the delegated contract code address.\n * @return the address of the EIP-7702 authorized contract.\n */\n function _getEip7702Delegate(address sender) internal view returns (address) {\n\n bytes32 senderCode;\n\n assembly (\"memory-safe\") {\n extcodecopy(sender, 0, 0, 23)\n senderCode := mload(0)\n }\n // To be a valid EIP-7702 delegate, the first 3 bytes are EIP7702_PREFIX\n // followed by the delegate address\n if (bytes3(senderCode) != EIP7702_PREFIX) {\n // instead of just \"not an EIP-7702 delegate\", if some info.\n require(sender.code.length > 0, \"sender has no code\");\n revert(\"not an EIP-7702 delegate\");\n }\n return address(bytes20(senderCode << 24));\n }\n}\n" + }, + "contracts/core/EntryPoint.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.28;\n/* solhint-disable avoid-low-level-calls */\n/* solhint-disable no-inline-assembly */\n\nimport \"../interfaces/IAccount.sol\";\nimport \"../interfaces/IAccountExecute.sol\";\nimport \"../interfaces/IEntryPoint.sol\";\nimport \"../interfaces/IPaymaster.sol\";\n\nimport \"./UserOperationLib.sol\";\nimport \"./StakeManager.sol\";\nimport \"./NonceManager.sol\";\nimport \"./Helpers.sol\";\nimport \"./SenderCreator.sol\";\nimport \"./Eip7702Support.sol\";\nimport \"../utils/Exec.sol\";\n\nimport \"@openzeppelin/contracts/utils/ReentrancyGuardTransient.sol\";\nimport \"@openzeppelin/contracts/utils/introspection/ERC165.sol\";\nimport \"@openzeppelin/contracts/utils/cryptography/EIP712.sol\";\n\n/**\n * Account-Abstraction (EIP-4337) singleton EntryPoint v0.8 implementation.\n * Only one instance required on each chain.\n * @custom:security-contact https://bounty.ethereum.org\n */\ncontract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuardTransient, ERC165, EIP712 {\n\n using UserOperationLib for PackedUserOperation;\n\n /**\n * internal-use constants\n */\n\n // allow some slack for future gas price changes.\n uint256 private constant INNER_GAS_OVERHEAD = 10000;\n\n // Marker for inner call revert on out of gas\n bytes32 private constant INNER_OUT_OF_GAS = hex\"deaddead\";\n bytes32 private constant INNER_REVERT_LOW_PREFUND = hex\"deadaa51\";\n\n uint256 private constant REVERT_REASON_MAX_LEN = 2048;\n // Penalty charged for either unused execution gas or postOp gas\n uint256 private constant UNUSED_GAS_PENALTY_PERCENT = 10;\n // Threshold below which no penalty would be charged\n uint256 private constant PENALTY_GAS_THRESHOLD = 40000;\n\n SenderCreator private immutable _senderCreator = new SenderCreator();\n\n string constant internal DOMAIN_NAME = \"ERC4337\";\n string constant internal DOMAIN_VERSION = \"1\";\n\n constructor() EIP712(DOMAIN_NAME, DOMAIN_VERSION) {\n }\n\n /// @inheritdoc IEntryPoint\n function handleOps(\n PackedUserOperation[] calldata ops,\n address payable beneficiary\n ) external nonReentrant {\n uint256 opslen = ops.length;\n UserOpInfo[] memory opInfos = new UserOpInfo[](opslen);\n unchecked {\n _iterateValidationPhase(ops, opInfos, address(0), 0);\n\n uint256 collected = 0;\n emit BeforeExecution();\n\n for (uint256 i = 0; i < opslen; i++) {\n collected += _executeUserOp(i, ops[i], opInfos[i]);\n }\n\n _compensate(beneficiary, collected);\n }\n }\n\n /// @inheritdoc IEntryPoint\n function handleAggregatedOps(\n UserOpsPerAggregator[] calldata opsPerAggregator,\n address payable beneficiary\n ) external nonReentrant {\n\n unchecked {\n uint256 opasLen = opsPerAggregator.length;\n uint256 totalOps = 0;\n for (uint256 i = 0; i < opasLen; i++) {\n UserOpsPerAggregator calldata opa = opsPerAggregator[i];\n PackedUserOperation[] calldata ops = opa.userOps;\n IAggregator aggregator = opa.aggregator;\n\n // address(1) is special marker of \"signature error\"\n require(\n address(aggregator) != address(1),\n SignatureValidationFailed(address(aggregator))\n );\n\n if (address(aggregator) != address(0)) {\n // solhint-disable-next-line no-empty-blocks\n try aggregator.validateSignatures(ops, opa.signature) {} catch {\n revert SignatureValidationFailed(address(aggregator));\n }\n }\n\n totalOps += ops.length;\n }\n\n UserOpInfo[] memory opInfos = new UserOpInfo[](totalOps);\n\n uint256 opIndex = 0;\n for (uint256 a = 0; a < opasLen; a++) {\n UserOpsPerAggregator calldata opa = opsPerAggregator[a];\n PackedUserOperation[] calldata ops = opa.userOps;\n IAggregator aggregator = opa.aggregator;\n\n opIndex += _iterateValidationPhase(ops, opInfos, address(aggregator), opIndex);\n }\n\n emit BeforeExecution();\n\n uint256 collected = 0;\n opIndex = 0;\n for (uint256 a = 0; a < opasLen; a++) {\n UserOpsPerAggregator calldata opa = opsPerAggregator[a];\n emit SignatureAggregatorChanged(address(opa.aggregator));\n PackedUserOperation[] calldata ops = opa.userOps;\n uint256 opslen = ops.length;\n\n for (uint256 i = 0; i < opslen; i++) {\n collected += _executeUserOp(opIndex, ops[i], opInfos[opIndex]);\n opIndex++;\n }\n }\n\n _compensate(beneficiary, collected);\n }\n }\n\n /// @inheritdoc IEntryPoint\n function getUserOpHash(\n PackedUserOperation calldata userOp\n ) public view returns (bytes32) {\n bytes32 overrideInitCodeHash = Eip7702Support._getEip7702InitCodeHashOverride(userOp);\n return\n MessageHashUtils.toTypedDataHash(getDomainSeparatorV4(), userOp.hash(overrideInitCodeHash));\n }\n\n /// @inheritdoc IEntryPoint\n function getSenderAddress(bytes calldata initCode) external {\n address sender = senderCreator().createSender(initCode);\n revert SenderAddressResult(sender);\n }\n\n /// @inheritdoc IEntryPoint\n function senderCreator() public view virtual returns (ISenderCreator) {\n return _senderCreator;\n }\n\n /// @inheritdoc IEntryPoint\n function delegateAndRevert(address target, bytes calldata data) external {\n (bool success, bytes memory ret) = target.delegatecall(data);\n revert DelegateAndRevert(success, ret);\n }\n\n function getPackedUserOpTypeHash() external pure returns (bytes32) {\n return UserOperationLib.PACKED_USEROP_TYPEHASH;\n }\n\n function getDomainSeparatorV4() public virtual view returns (bytes32) {\n return _domainSeparatorV4();\n }\n\n /// @inheritdoc IERC165\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n // note: solidity \"type(IEntryPoint).interfaceId\" is without inherited methods but we want to check everything\n return interfaceId == (type(IEntryPoint).interfaceId ^ type(IStakeManager).interfaceId ^ type(INonceManager).interfaceId) ||\n interfaceId == type(IEntryPoint).interfaceId ||\n interfaceId == type(IStakeManager).interfaceId ||\n interfaceId == type(INonceManager).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * Compensate the caller's beneficiary address with the collected fees of all UserOperations.\n * @param beneficiary - The address to receive the fees.\n * @param amount - Amount to transfer.\n */\n function _compensate(address payable beneficiary, uint256 amount) internal virtual {\n require(beneficiary != address(0), \"AA90 invalid beneficiary\");\n (bool success,) = beneficiary.call{value: amount}(\"\");\n require(success, \"AA91 failed send to beneficiary\");\n }\n\n /**\n * Execute a user operation.\n * @param opIndex - Index into the opInfo array.\n * @param userOp - The userOp to execute.\n * @param opInfo - The opInfo filled by validatePrepayment for this userOp.\n * @return collected - The total amount this userOp paid.\n */\n function _executeUserOp(\n uint256 opIndex,\n PackedUserOperation calldata userOp,\n UserOpInfo memory opInfo\n )\n internal virtual\n returns (uint256 collected) {\n uint256 preGas = gasleft();\n bytes memory context = _getMemoryBytesFromOffset(opInfo.contextOffset);\n bool success;\n {\n uint256 saveFreePtr = _getFreePtr();\n bytes calldata callData = userOp.callData;\n bytes memory innerCall;\n bytes4 methodSig;\n assembly (\"memory-safe\") {\n let len := callData.length\n if gt(len, 3) {\n methodSig := calldataload(callData.offset)\n }\n }\n if (methodSig == IAccountExecute.executeUserOp.selector) {\n bytes memory executeUserOp = abi.encodeCall(IAccountExecute.executeUserOp, (userOp, opInfo.userOpHash));\n innerCall = abi.encodeCall(this.innerHandleOp, (executeUserOp, opInfo, context));\n } else\n {\n innerCall = abi.encodeCall(this.innerHandleOp, (callData, opInfo, context));\n }\n assembly (\"memory-safe\") {\n success := call(gas(), address(), 0, add(innerCall, 0x20), mload(innerCall), 0, 32)\n collected := mload(0)\n }\n _restoreFreePtr(saveFreePtr);\n }\n if (!success) {\n bytes32 innerRevertCode;\n assembly (\"memory-safe\") {\n let len := returndatasize()\n if eq(32, len) {\n returndatacopy(0, 0, 32)\n innerRevertCode := mload(0)\n }\n }\n if (innerRevertCode == INNER_OUT_OF_GAS) {\n // handleOps was called with gas limit too low. abort entire bundle.\n // can only be caused by bundler (leaving not enough gas for inner call)\n revert FailedOp(opIndex, \"AA95 out of gas\");\n } else if (innerRevertCode == INNER_REVERT_LOW_PREFUND) {\n // innerCall reverted on prefund too low. treat entire prefund as \"gas cost\"\n uint256 actualGas = preGas - gasleft() + opInfo.preOpGas;\n uint256 actualGasCost = opInfo.prefund;\n _emitPrefundTooLow(opInfo);\n _emitUserOperationEvent(opInfo, false, actualGasCost, actualGas);\n collected = actualGasCost;\n } else {\n uint256 freePtr = _getFreePtr();\n emit PostOpRevertReason(\n opInfo.userOpHash,\n opInfo.mUserOp.sender,\n opInfo.mUserOp.nonce,\n Exec.getReturnData(REVERT_REASON_MAX_LEN)\n );\n _restoreFreePtr(freePtr);\n\n uint256 actualGas = preGas - gasleft() + opInfo.preOpGas;\n collected = _postExecution(\n IPaymaster.PostOpMode.postOpReverted,\n opInfo,\n context,\n actualGas\n );\n }\n }\n }\n\n /**\n * Emit the UserOperationEvent for the given UserOperation.\n *\n * @param opInfo - The details of the current UserOperation.\n * @param success - Whether the execution of the UserOperation has succeeded or not.\n * @param actualGasCost - The actual cost of the consumed gas charged from the sender or the paymaster.\n * @param actualGas - The actual amount of gas used.\n */\n function _emitUserOperationEvent(UserOpInfo memory opInfo, bool success, uint256 actualGasCost, uint256 actualGas) internal virtual {\n emit UserOperationEvent(\n opInfo.userOpHash,\n opInfo.mUserOp.sender,\n opInfo.mUserOp.paymaster,\n opInfo.mUserOp.nonce,\n success,\n actualGasCost,\n actualGas\n );\n }\n\n /**\n * Emit the UserOperationPrefundTooLow event for the given UserOperation.\n *\n * @param opInfo - The details of the current UserOperation.\n */\n function _emitPrefundTooLow(UserOpInfo memory opInfo) internal virtual {\n emit UserOperationPrefundTooLow(\n opInfo.userOpHash,\n opInfo.mUserOp.sender,\n opInfo.mUserOp.nonce\n );\n }\n\n /**\n * Iterate over calldata PackedUserOperation array and perform account and paymaster validation.\n * @notice UserOpInfo is a global array of all UserOps while PackedUserOperation is grouped per aggregator.\n *\n * @param ops - an array of UserOps to be validated\n * @param opInfos - an array of UserOp metadata being read and filled in during this function's execution\n * @param expectedAggregator - an address of the aggregator specified for a given UserOp if any, or address(0)\n * @param opIndexOffset - an offset for the index between 'ops' and 'opInfos' arrays, see the notice.\n * @return opsLen - processed UserOps (length of \"ops\" array)\n */\n function _iterateValidationPhase(\n PackedUserOperation[] calldata ops,\n UserOpInfo[] memory opInfos,\n address expectedAggregator,\n uint256 opIndexOffset\n ) internal returns (uint256 opsLen){\n unchecked {\n opsLen = ops.length;\n for (uint256 i = 0; i < opsLen; i++) {\n UserOpInfo memory opInfo = opInfos[opIndexOffset + i];\n (\n uint256 validationData,\n uint256 pmValidationData\n ) = _validatePrepayment(opIndexOffset + i, ops[i], opInfo);\n _validateAccountAndPaymasterValidationData(\n opIndexOffset + i,\n validationData,\n pmValidationData,\n expectedAggregator\n );\n }\n }\n }\n\n /**\n * A memory copy of UserOp static fields only.\n * Excluding: callData, initCode and signature. Replacing paymasterAndData with paymaster.\n */\n struct MemoryUserOp {\n address sender;\n uint256 nonce;\n uint256 verificationGasLimit;\n uint256 callGasLimit;\n uint256 paymasterVerificationGasLimit;\n uint256 paymasterPostOpGasLimit;\n uint256 preVerificationGas;\n address paymaster;\n uint256 maxFeePerGas;\n uint256 maxPriorityFeePerGas;\n }\n\n struct UserOpInfo {\n MemoryUserOp mUserOp;\n bytes32 userOpHash;\n uint256 prefund;\n uint256 contextOffset;\n uint256 preOpGas;\n }\n\n /**\n * Inner function to handle a UserOperation.\n * Must be declared \"external\" to open a call context, but it can only be called by handleOps.\n * @param callData - The callData to execute.\n * @param opInfo - The UserOpInfo struct.\n * @param context - The context bytes.\n * @return actualGasCost - the actual cost in eth this UserOperation paid for gas\n */\n function innerHandleOp(\n bytes memory callData,\n UserOpInfo memory opInfo,\n bytes calldata context\n ) external returns (uint256 actualGasCost) {\n uint256 preGas = gasleft();\n require(msg.sender == address(this), \"AA92 internal call only\");\n MemoryUserOp memory mUserOp = opInfo.mUserOp;\n\n uint256 callGasLimit = mUserOp.callGasLimit;\n unchecked {\n // handleOps was called with gas limit too low. abort entire bundle.\n if (\n gasleft() * 63 / 64 <\n callGasLimit +\n mUserOp.paymasterPostOpGasLimit +\n INNER_GAS_OVERHEAD\n ) {\n assembly (\"memory-safe\") {\n mstore(0, INNER_OUT_OF_GAS)\n revert(0, 32)\n }\n }\n }\n\n IPaymaster.PostOpMode mode = IPaymaster.PostOpMode.opSucceeded;\n if (callData.length > 0) {\n bool success = Exec.call(mUserOp.sender, 0, callData, callGasLimit);\n if (!success) {\n uint256 freePtr = _getFreePtr();\n bytes memory result = Exec.getReturnData(REVERT_REASON_MAX_LEN);\n if (result.length > 0) {\n emit UserOperationRevertReason(\n opInfo.userOpHash,\n mUserOp.sender,\n mUserOp.nonce,\n result\n );\n }\n _restoreFreePtr(freePtr);\n mode = IPaymaster.PostOpMode.opReverted;\n }\n }\n\n unchecked {\n uint256 actualGas = preGas - gasleft() + opInfo.preOpGas;\n return _postExecution(mode, opInfo, context, actualGas);\n }\n }\n\n /**\n * Copy general fields from userOp into the memory opInfo structure.\n * @param userOp - The user operation.\n * @param mUserOp - The memory user operation.\n */\n function _copyUserOpToMemory(\n PackedUserOperation calldata userOp,\n MemoryUserOp memory mUserOp\n ) internal virtual pure {\n mUserOp.sender = userOp.sender;\n mUserOp.nonce = userOp.nonce;\n (mUserOp.verificationGasLimit, mUserOp.callGasLimit) = UserOperationLib.unpackUints(userOp.accountGasLimits);\n mUserOp.preVerificationGas = userOp.preVerificationGas;\n (mUserOp.maxPriorityFeePerGas, mUserOp.maxFeePerGas) = UserOperationLib.unpackUints(userOp.gasFees);\n bytes calldata paymasterAndData = userOp.paymasterAndData;\n if (paymasterAndData.length > 0) {\n require(\n paymasterAndData.length >= UserOperationLib.PAYMASTER_DATA_OFFSET,\n \"AA93 invalid paymasterAndData\"\n );\n address paymaster;\n (paymaster, mUserOp.paymasterVerificationGasLimit, mUserOp.paymasterPostOpGasLimit) = UserOperationLib.unpackPaymasterStaticFields(paymasterAndData);\n require(paymaster != address(0), \"AA98 invalid paymaster\");\n mUserOp.paymaster = paymaster;\n }\n }\n\n /**\n * Get the required prefunded gas fee amount for an operation.\n *\n * @param mUserOp - The user operation in memory.\n * @return requiredPrefund - the required amount.\n */\n function _getRequiredPrefund(\n MemoryUserOp memory mUserOp\n ) internal virtual pure returns (uint256 requiredPrefund) {\n unchecked {\n uint256 requiredGas = mUserOp.verificationGasLimit +\n mUserOp.callGasLimit +\n mUserOp.paymasterVerificationGasLimit +\n mUserOp.paymasterPostOpGasLimit +\n mUserOp.preVerificationGas;\n\n requiredPrefund = requiredGas * mUserOp.maxFeePerGas;\n }\n }\n\n /**\n * Create sender smart contract account if init code is provided.\n * @param opIndex - The operation index.\n * @param opInfo - The operation info.\n * @param initCode - The init code for the smart contract account.\n */\n function _createSenderIfNeeded(\n uint256 opIndex,\n UserOpInfo memory opInfo,\n bytes calldata initCode\n ) internal virtual {\n if (initCode.length != 0) {\n address sender = opInfo.mUserOp.sender;\n if (Eip7702Support._isEip7702InitCode(initCode)) {\n if (initCode.length > 20) {\n // Already validated it is an EIP-7702 delegate (and hence, already has code) - see getUserOpHash()\n // Note: Can be called multiple times as long as an appropriate initCode is supplied\n senderCreator().initEip7702Sender{\n gas: opInfo.mUserOp.verificationGasLimit\n }(sender, initCode[20 :]);\n }\n return;\n }\n if (sender.code.length != 0)\n revert FailedOp(opIndex, \"AA10 sender already constructed\");\n if (initCode.length < 20) {\n revert FailedOp(opIndex, \"AA99 initCode too small\");\n }\n address sender1 = senderCreator().createSender{\n gas: opInfo.mUserOp.verificationGasLimit\n }(initCode);\n if (sender1 == address(0))\n revert FailedOp(opIndex, \"AA13 initCode failed or OOG\");\n if (sender1 != sender)\n revert FailedOp(opIndex, \"AA14 initCode must return sender\");\n if (sender1.code.length == 0)\n revert FailedOp(opIndex, \"AA15 initCode must create sender\");\n address factory = address(bytes20(initCode[0 : 20]));\n emit AccountDeployed(\n opInfo.userOpHash,\n sender,\n factory,\n opInfo.mUserOp.paymaster\n );\n }\n }\n\n /**\n * Call account.validateUserOp.\n * Revert (with FailedOp) in case validateUserOp reverts, or account didn't send required prefund.\n * Decrement account's deposit if needed.\n * @param opIndex - The operation index.\n * @param op - The user operation.\n * @param opInfo - The operation info.\n * @param requiredPrefund - The required prefund amount.\n * @return validationData - The account's validationData.\n */\n function _validateAccountPrepayment(\n uint256 opIndex,\n PackedUserOperation calldata op,\n UserOpInfo memory opInfo,\n uint256 requiredPrefund\n )\n internal virtual\n returns (\n uint256 validationData\n )\n {\n unchecked {\n MemoryUserOp memory mUserOp = opInfo.mUserOp;\n address sender = mUserOp.sender;\n _createSenderIfNeeded(opIndex, opInfo, op.initCode);\n address paymaster = mUserOp.paymaster;\n uint256 missingAccountFunds = 0;\n if (paymaster == address(0)) {\n uint256 bal = balanceOf(sender);\n missingAccountFunds = bal > requiredPrefund\n ? 0\n : requiredPrefund - bal;\n }\n validationData = _callValidateUserOp(opIndex, op, opInfo, missingAccountFunds);\n if (paymaster == address(0)) {\n if (!_tryDecrementDeposit(sender, requiredPrefund)) {\n revert FailedOp(opIndex, \"AA21 didn't pay prefund\");\n }\n }\n }\n }\n\n /**\n * Make a call to the sender.validateUserOp() function.\n * Handle wrong output size by reverting with a FailedOp error.\n *\n * @param opIndex - index of the UserOperation in the bundle.\n * @param op - the packed UserOperation object.\n * @param opInfo - the in-memory UserOperation information.\n * @param missingAccountFunds - the amount of deposit the account has to make to cover the UserOperation gas.\n */\n function _callValidateUserOp(\n uint256 opIndex,\n PackedUserOperation calldata op,\n UserOpInfo memory opInfo,\n uint256 missingAccountFunds\n )\n internal virtual returns (uint256 validationData) {\n uint256 gasLimit = opInfo.mUserOp.verificationGasLimit;\n address sender = opInfo.mUserOp.sender;\n bool success;\n {\n uint256 saveFreePtr = _getFreePtr();\n bytes memory callData = abi.encodeCall(IAccount.validateUserOp, (op, opInfo.userOpHash, missingAccountFunds));\n assembly (\"memory-safe\"){\n success := call(gasLimit, sender, 0, add(callData, 0x20), mload(callData), 0, 32)\n validationData := mload(0)\n // any return data size other than 32 is considered failure\n if iszero(eq(returndatasize(), 32)) {\n success := 0\n }\n }\n _restoreFreePtr(saveFreePtr);\n }\n if (!success) {\n if (sender.code.length == 0) {\n revert FailedOp(opIndex, \"AA20 account not deployed\");\n } else {\n revert FailedOpWithRevert(opIndex, \"AA23 reverted\", Exec.getReturnData(REVERT_REASON_MAX_LEN));\n }\n }\n }\n\n /**\n * In case the request has a paymaster:\n * - Validate paymaster has enough deposit.\n * - Call paymaster.validatePaymasterUserOp.\n * - Revert with proper FailedOp in case paymaster reverts.\n * - Decrement paymaster's deposit.\n * @param opIndex - The operation index.\n * @param op - The user operation.\n * @param opInfo - The operation info.\n * @return context - The Paymaster-provided value to be passed to the 'postOp' function later\n * @return validationData - The Paymaster's validationData.\n */\n function _validatePaymasterPrepayment(\n uint256 opIndex,\n PackedUserOperation calldata op,\n UserOpInfo memory opInfo\n ) internal virtual returns (bytes memory context, uint256 validationData) {\n unchecked {\n uint256 preGas = gasleft();\n MemoryUserOp memory mUserOp = opInfo.mUserOp;\n address paymaster = mUserOp.paymaster;\n uint256 requiredPreFund = opInfo.prefund;\n if (!_tryDecrementDeposit(paymaster, requiredPreFund)) {\n revert FailedOp(opIndex, \"AA31 paymaster deposit too low\");\n }\n uint256 pmVerificationGasLimit = mUserOp.paymasterVerificationGasLimit;\n (context, validationData) = _callValidatePaymasterUserOp(opIndex, op, opInfo);\n if (preGas - gasleft() > pmVerificationGasLimit) {\n revert FailedOp(opIndex, \"AA36 over paymasterVerificationGasLimit\");\n }\n }\n }\n\n function _callValidatePaymasterUserOp(\n uint256 opIndex,\n PackedUserOperation calldata op,\n UserOpInfo memory opInfo\n ) internal returns (bytes memory context, uint256 validationData) {\n uint256 freePtr = _getFreePtr();\n bytes memory validatePaymasterCall = abi.encodeCall(\n IPaymaster.validatePaymasterUserOp,\n (op, opInfo.userOpHash, opInfo.prefund)\n );\n address paymaster = opInfo.mUserOp.paymaster;\n uint256 paymasterVerificationGasLimit = opInfo.mUserOp.paymasterVerificationGasLimit;\n bool success;\n uint256 contextLength;\n uint256 contextOffset;\n uint256 maxContextLength;\n uint256 len;\n assembly (\"memory-safe\") {\n success := call(paymasterVerificationGasLimit, paymaster, 0, add(validatePaymasterCall, 0x20), mload(validatePaymasterCall), 0, 0)\n len := returndatasize()\n // return data from validatePaymasterUserOp is (bytes context, validationData)\n // encoded as:\n // 32 bytes offset of context (always 64)\n // 32 bytes of validationData\n // 32 bytes of context length\n // context data (rounded up, to 32 bytes boundary)\n // so entire buffer size is (at least) 96+content.length.\n //\n // we use freePtr, fetched before calling encodeCall, as return data pointer.\n // this way we reuse that memory without unnecessary memory expansion\n returndatacopy(freePtr, 0, len)\n validationData := mload(add(freePtr, 32))\n contextOffset := mload(freePtr)\n maxContextLength := sub(len, 96)\n context := add(freePtr, 64)\n contextLength := mload(context)\n }\n\n unchecked {\n if (!success || contextOffset != 64 || contextLength + 31 < maxContextLength) {\n revert FailedOpWithRevert(opIndex, \"AA33 reverted\", Exec.getReturnData(REVERT_REASON_MAX_LEN));\n }\n }\n finalizeAllocation(freePtr, len);\n }\n\n /**\n * Revert if either account validationData or paymaster validationData is expired.\n * @param opIndex - The operation index.\n * @param validationData - The account validationData.\n * @param paymasterValidationData - The paymaster validationData.\n * @param expectedAggregator - The expected aggregator.\n */\n function _validateAccountAndPaymasterValidationData(\n uint256 opIndex,\n uint256 validationData,\n uint256 paymasterValidationData,\n address expectedAggregator\n ) internal virtual view {\n (address aggregator, bool outOfTimeRange) = _getValidationData(\n validationData\n );\n if (expectedAggregator != aggregator) {\n revert FailedOp(opIndex, \"AA24 signature error\");\n }\n if (outOfTimeRange) {\n revert FailedOp(opIndex, \"AA22 expired or not due\");\n }\n // pmAggregator is not a real signature aggregator: we don't have logic to handle it as address.\n // Non-zero address means that the paymaster fails due to some signature check (which is ok only during estimation).\n address pmAggregator;\n (pmAggregator, outOfTimeRange) = _getValidationData(\n paymasterValidationData\n );\n if (pmAggregator != address(0)) {\n revert FailedOp(opIndex, \"AA34 signature error\");\n }\n if (outOfTimeRange) {\n revert FailedOp(opIndex, \"AA32 paymaster expired or not due\");\n }\n }\n\n /**\n * Parse validationData into its components.\n * @param validationData - The packed validation data (sigFailed, validAfter, validUntil).\n * @return aggregator the aggregator of the validationData\n * @return outOfTimeRange true if current time is outside the time range of this validationData.\n */\n function _getValidationData(\n uint256 validationData\n ) internal virtual view returns (address aggregator, bool outOfTimeRange) {\n if (validationData == 0) {\n return (address(0), false);\n }\n ValidationData memory data = _parseValidationData(validationData);\n // solhint-disable-next-line not-rely-on-time\n outOfTimeRange = block.timestamp > data.validUntil || block.timestamp <= data.validAfter;\n aggregator = data.aggregator;\n }\n\n /**\n * Validate account and paymaster (if defined) and\n * also make sure total validation doesn't exceed verificationGasLimit.\n * This method is called off-chain (simulateValidation()) and on-chain (from handleOps)\n * @param opIndex - The index of this userOp into the \"opInfos\" array.\n * @param userOp - The packed calldata UserOperation structure to validate.\n * @param outOpInfo - The empty unpacked in-memory UserOperation structure that will be filled in here.\n *\n * @return validationData - The account's validationData.\n * @return paymasterValidationData - The paymaster's validationData.\n */\n function _validatePrepayment(\n uint256 opIndex,\n PackedUserOperation calldata userOp,\n UserOpInfo memory outOpInfo\n )\n internal virtual\n returns (uint256 validationData, uint256 paymasterValidationData)\n {\n uint256 preGas = gasleft();\n MemoryUserOp memory mUserOp = outOpInfo.mUserOp;\n _copyUserOpToMemory(userOp, mUserOp);\n\n // getUserOpHash uses temporary allocations, no required after it returns\n uint256 freePtr = _getFreePtr();\n outOpInfo.userOpHash = getUserOpHash(userOp);\n _restoreFreePtr(freePtr);\n\n // Validate all numeric values in userOp are well below 128 bit, so they can safely be added\n // and multiplied without causing overflow.\n uint256 verificationGasLimit = mUserOp.verificationGasLimit;\n uint256 maxGasValues = mUserOp.preVerificationGas |\n verificationGasLimit |\n mUserOp.callGasLimit |\n mUserOp.paymasterVerificationGasLimit |\n mUserOp.paymasterPostOpGasLimit |\n mUserOp.maxFeePerGas |\n mUserOp.maxPriorityFeePerGas;\n require(maxGasValues <= type(uint120).max, FailedOp(opIndex, \"AA94 gas values overflow\"));\n\n uint256 requiredPreFund = _getRequiredPrefund(mUserOp);\n outOpInfo.prefund = requiredPreFund;\n validationData = _validateAccountPrepayment(\n opIndex,\n userOp,\n outOpInfo,\n requiredPreFund\n );\n\n require(\n _validateAndUpdateNonce(mUserOp.sender, mUserOp.nonce),\n FailedOp(opIndex, \"AA25 invalid account nonce\")\n );\n\n unchecked {\n if (preGas - gasleft() > verificationGasLimit) {\n revert FailedOp(opIndex, \"AA26 over verificationGasLimit\");\n }\n }\n\n bytes memory context;\n if (mUserOp.paymaster != address(0)) {\n (context, paymasterValidationData) = _validatePaymasterPrepayment(\n opIndex,\n userOp,\n outOpInfo\n );\n }\n unchecked {\n outOpInfo.contextOffset = _getOffsetOfMemoryBytes(context);\n outOpInfo.preOpGas = preGas - gasleft() + userOp.preVerificationGas;\n }\n }\n\n /**\n * Process post-operation, called just after the callData is executed.\n * If a paymaster is defined and its validation returned a non-empty context, its postOp is called.\n * The excess amount is refunded to the account (or paymaster - if it was used in the request).\n * @param mode - Whether is called from innerHandleOp, or outside (postOpReverted).\n * @param opInfo - UserOp fields and info collected during validation.\n * @param context - The context returned in validatePaymasterUserOp.\n * @param actualGas - The gas used so far by this user operation.\n *\n * @return actualGasCost - the actual cost in eth this UserOperation paid for gas\n */\n function _postExecution(\n IPaymaster.PostOpMode mode,\n UserOpInfo memory opInfo,\n bytes memory context,\n uint256 actualGas\n ) internal virtual returns (uint256 actualGasCost) {\n uint256 preGas = gasleft();\n unchecked {\n address refundAddress;\n MemoryUserOp memory mUserOp = opInfo.mUserOp;\n uint256 gasPrice = _getUserOpGasPrice(mUserOp);\n\n address paymaster = mUserOp.paymaster;\n // Calculating a penalty for unused execution gas\n {\n uint256 executionGasUsed = actualGas - opInfo.preOpGas;\n // this check is required for the gas used within EntryPoint and not covered by explicit gas limits\n actualGas += _getUnusedGasPenalty(executionGasUsed, mUserOp.callGasLimit);\n }\n uint256 postOpUnusedGasPenalty;\n if (paymaster == address(0)) {\n refundAddress = mUserOp.sender;\n } else {\n refundAddress = paymaster;\n if (context.length > 0) {\n actualGasCost = actualGas * gasPrice;\n uint256 postOpPreGas = gasleft();\n if (mode != IPaymaster.PostOpMode.postOpReverted) {\n try IPaymaster(paymaster).postOp{\n gas: mUserOp.paymasterPostOpGasLimit\n }(mode, context, actualGasCost, gasPrice)\n // solhint-disable-next-line no-empty-blocks\n {} catch {\n bytes memory reason = Exec.getReturnData(REVERT_REASON_MAX_LEN);\n revert PostOpReverted(reason);\n }\n }\n // Calculating a penalty for unused postOp gas\n // note that if postOp is reverted, the maximum penalty (10% of postOpGasLimit) is charged.\n uint256 postOpGasUsed = postOpPreGas - gasleft();\n postOpUnusedGasPenalty = _getUnusedGasPenalty(postOpGasUsed, mUserOp.paymasterPostOpGasLimit);\n }\n }\n actualGas += preGas - gasleft() + postOpUnusedGasPenalty;\n actualGasCost = actualGas * gasPrice;\n uint256 prefund = opInfo.prefund;\n if (prefund < actualGasCost) {\n if (mode == IPaymaster.PostOpMode.postOpReverted) {\n actualGasCost = prefund;\n _emitPrefundTooLow(opInfo);\n _emitUserOperationEvent(opInfo, false, actualGasCost, actualGas);\n } else {\n assembly (\"memory-safe\") {\n mstore(0, INNER_REVERT_LOW_PREFUND)\n revert(0, 32)\n }\n }\n } else {\n uint256 refund = prefund - actualGasCost;\n _incrementDeposit(refundAddress, refund);\n bool success = mode == IPaymaster.PostOpMode.opSucceeded;\n _emitUserOperationEvent(opInfo, success, actualGasCost, actualGas);\n }\n } // unchecked\n }\n\n /**\n * The gas price this UserOp agrees to pay.\n * Relayer/block builder might submit the TX with higher priorityFee, but the user should not be affected.\n * @param mUserOp - The userOp to get the gas price from.\n */\n function _getUserOpGasPrice(\n MemoryUserOp memory mUserOp\n ) internal view returns (uint256) {\n unchecked {\n uint256 maxFeePerGas = mUserOp.maxFeePerGas;\n uint256 maxPriorityFeePerGas = mUserOp.maxPriorityFeePerGas;\n return min(maxFeePerGas, maxPriorityFeePerGas + block.basefee);\n }\n }\n\n /**\n * The offset of the given bytes in memory.\n * @param data - The bytes to get the offset of.\n */\n function _getOffsetOfMemoryBytes(\n bytes memory data\n ) internal pure returns (uint256 offset) {\n assembly (\"memory-safe\") {\n offset := data\n }\n }\n\n /**\n * The bytes in memory at the given offset.\n * @param offset - The offset to get the bytes from.\n */\n function _getMemoryBytesFromOffset(\n uint256 offset\n ) internal pure returns (bytes memory data) {\n assembly (\"memory-safe\") {\n data := offset\n }\n }\n\n /**\n * save free memory pointer.\n * save \"free memory\" pointer, so that it can be restored later using restoreFreePtr.\n * This reduce unneeded memory expansion, and reduce memory expansion cost.\n * NOTE: all dynamic allocations between saveFreePtr and restoreFreePtr MUST NOT be used after restoreFreePtr is called.\n */\n function _getFreePtr() internal pure returns (uint256 ptr) {\n assembly (\"memory-safe\") {\n ptr := mload(0x40)\n }\n }\n\n /**\n * restore free memory pointer.\n * any allocated memory since saveFreePtr is cleared, and MUST NOT be accessed later.\n */\n function _restoreFreePtr(uint256 ptr) internal pure {\n assembly (\"memory-safe\") {\n mstore(0x40, ptr)\n }\n }\n\n function _getUnusedGasPenalty(uint256 gasUsed, uint256 gasLimit) internal pure returns (uint256) {\n unchecked {\n if (gasLimit <= gasUsed + PENALTY_GAS_THRESHOLD) {\n return 0;\n }\n uint256 unusedGas = gasLimit - gasUsed;\n uint256 unusedGasPenalty = (unusedGas * UNUSED_GAS_PENALTY_PERCENT) / 100;\n return unusedGasPenalty;\n }\n }\n}\n" + }, + "contracts/core/Helpers.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.28;\n\n/* solhint-disable no-inline-assembly */\n\n\n /*\n * For simulation purposes, validateUserOp (and validatePaymasterUserOp)\n * must return this value in case of signature failure, instead of revert.\n */\nuint256 constant SIG_VALIDATION_FAILED = 1;\n\n\n/*\n * For simulation purposes, validateUserOp (and validatePaymasterUserOp)\n * return this value on success.\n */\nuint256 constant SIG_VALIDATION_SUCCESS = 0;\n\n\n/**\n * Returned data from validateUserOp.\n * validateUserOp returns a uint256, which is created by `_packedValidationData` and\n * parsed by `_parseValidationData`.\n * @param aggregator - address(0) - The account validated the signature by itself.\n * address(1) - The account failed to validate the signature.\n * otherwise - This is an address of a signature aggregator that must\n * be used to validate the signature.\n * @param validAfter - This UserOp is valid only after this timestamp.\n * @param validUntil - Last timestamp this operation is valid at, or 0 for \"indefinitely\".\n */\nstruct ValidationData {\n address aggregator;\n uint48 validAfter;\n uint48 validUntil;\n}\n\n/**\n * Extract aggregator/sigFailed, validAfter, validUntil.\n * Also convert zero validUntil to type(uint48).max.\n * @param validationData - The packed validation data.\n * @return data - The unpacked in-memory validation data.\n */\nfunction _parseValidationData(\n uint256 validationData\n) pure returns (ValidationData memory data) {\n address aggregator = address(uint160(validationData));\n uint48 validUntil = uint48(validationData >> 160);\n if (validUntil == 0) {\n validUntil = type(uint48).max;\n }\n uint48 validAfter = uint48(validationData >> (48 + 160));\n return ValidationData(aggregator, validAfter, validUntil);\n}\n\n/**\n * Helper to pack the return value for validateUserOp.\n * @param data - The ValidationData to pack.\n * @return the packed validation data.\n */\nfunction _packValidationData(\n ValidationData memory data\n) pure returns (uint256) {\n return\n uint160(data.aggregator) |\n (uint256(data.validUntil) << 160) |\n (uint256(data.validAfter) << (160 + 48));\n}\n\n/**\n * Helper to pack the return value for validateUserOp, when not using an aggregator.\n * @param sigFailed - True for signature failure, false for success.\n * @param validUntil - Last timestamp this operation is valid at, or 0 for \"indefinitely\".\n * @param validAfter - First timestamp this UserOperation is valid.\n * @return the packed validation data.\n */\nfunction _packValidationData(\n bool sigFailed,\n uint48 validUntil,\n uint48 validAfter\n) pure returns (uint256) {\n return\n (sigFailed ? SIG_VALIDATION_FAILED : SIG_VALIDATION_SUCCESS) |\n (uint256(validUntil) << 160) |\n (uint256(validAfter) << (160 + 48));\n}\n\n/**\n * keccak function over calldata.\n * @dev copy calldata into memory, do keccak and drop allocated memory. Strangely, this is more efficient than letting solidity do it.\n *\n * @param data - the calldata bytes array to perform keccak on.\n * @return ret - the keccak hash of the 'data' array.\n */\n function calldataKeccak(bytes calldata data) pure returns (bytes32 ret) {\n assembly (\"memory-safe\") {\n let mem := mload(0x40)\n let len := data.length\n calldatacopy(mem, data.offset, len)\n ret := keccak256(mem, len)\n }\n }\n\n\n/**\n * The minimum of two numbers.\n * @param a - First number.\n * @param b - Second number.\n * @return - the minimum value.\n */\n function min(uint256 a, uint256 b) pure returns (uint256) {\n return a < b ? a : b;\n }\n\n/**\n * standard solidity memory allocation finalization.\n * copied from solidity generated code\n * @param memPointer - The current memory pointer\n * @param allocationSize - Bytes allocated from memPointer.\n */\n function finalizeAllocation(uint256 memPointer, uint256 allocationSize) pure {\n\n assembly (\"memory-safe\"){\n finalize_allocation(memPointer, allocationSize)\n\n function finalize_allocation(memPtr, size) {\n let newFreePtr := add(memPtr, round_up_to_mul_of_32(size))\n mstore(64, newFreePtr)\n }\n\n function round_up_to_mul_of_32(value) -> result {\n result := and(add(value, 31), not(31))\n }\n }\n }\n" + }, + "contracts/core/NonceManager.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.28;\n\nimport \"../interfaces/INonceManager.sol\";\n\n/**\n * nonce management functionality\n */\nabstract contract NonceManager is INonceManager {\n\n /**\n * The next valid sequence number for a given nonce key.\n */\n mapping(address => mapping(uint192 => uint256)) public nonceSequenceNumber;\n\n /// @inheritdoc INonceManager\n function getNonce(address sender, uint192 key)\n public view override returns (uint256 nonce) {\n return nonceSequenceNumber[sender][key] | (uint256(key) << 64);\n }\n\n /// @inheritdoc INonceManager\n function incrementNonce(uint192 key) external override {\n nonceSequenceNumber[msg.sender][key]++;\n }\n\n /**\n * validate nonce uniqueness for this account.\n * called just after validateUserOp()\n * @return true if the nonce was incremented successfully.\n * false if the current nonce doesn't match the given one.\n */\n function _validateAndUpdateNonce(address sender, uint256 nonce) internal returns (bool) {\n\n uint192 key = uint192(nonce >> 64);\n uint64 seq = uint64(nonce);\n return nonceSequenceNumber[sender][key]++ == seq;\n }\n\n}\n" + }, + "contracts/core/SenderCreator.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.28;\n/* solhint-disable avoid-low-level-calls */\n/* solhint-disable no-inline-assembly */\n\nimport \"../interfaces/ISenderCreator.sol\";\nimport \"../interfaces/IEntryPoint.sol\";\nimport \"../utils/Exec.sol\";\n\n/**\n * Helper contract for EntryPoint, to call userOp.initCode from a \"neutral\" address,\n * which is explicitly not the entryPoint itself.\n */\ncontract SenderCreator is ISenderCreator {\n address public immutable entryPoint;\n\n constructor(){\n entryPoint = msg.sender;\n }\n\n uint256 private constant REVERT_REASON_MAX_LEN = 2048;\n\n /**\n * Call the \"initCode\" factory to create and return the sender account address.\n * @param initCode - The initCode value from a UserOp. contains 20 bytes of factory address,\n * followed by calldata.\n * @return sender - The returned address of the created account, or zero address on failure.\n */\n function createSender(\n bytes calldata initCode\n ) external returns (address sender) {\n require(msg.sender == entryPoint, \"AA97 should call from EntryPoint\");\n address factory = address(bytes20(initCode[0 : 20]));\n\n bytes memory initCallData = initCode[20 :];\n bool success;\n assembly (\"memory-safe\") {\n success := call(\n gas(),\n factory,\n 0,\n add(initCallData, 0x20),\n mload(initCallData),\n 0,\n 32\n )\n if success {\n sender := mload(0)\n }\n }\n }\n\n /// @inheritdoc ISenderCreator\n function initEip7702Sender(\n address sender,\n bytes memory initCallData\n ) external {\n require(msg.sender == entryPoint, \"AA97 should call from EntryPoint\");\n bool success;\n assembly (\"memory-safe\") {\n success := call(\n gas(),\n sender,\n 0,\n add(initCallData, 0x20),\n mload(initCallData),\n 0,\n 0\n )\n }\n if (!success) {\n bytes memory result = Exec.getReturnData(REVERT_REASON_MAX_LEN);\n revert IEntryPoint.FailedOpWithRevert(0, \"AA13 EIP7702 sender init failed\", result);\n }\n }\n}\n" + }, + "contracts/core/StakeManager.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.28;\n\nimport \"../interfaces/IStakeManager.sol\";\n\n/* solhint-disable avoid-low-level-calls */\n/* solhint-disable not-rely-on-time */\n\n/**\n * Manage deposits and stakes.\n * Deposit is just a balance used to pay for UserOperations (either by a paymaster or an account).\n * Stake is value locked for at least \"unstakeDelay\" by a paymaster.\n */\nabstract contract StakeManager is IStakeManager {\n /// maps paymaster to their deposits and stakes\n mapping(address => DepositInfo) private deposits;\n\n /// @inheritdoc IStakeManager\n function getDepositInfo(\n address account\n ) external view returns (DepositInfo memory info) {\n return deposits[account];\n }\n\n /**\n * Internal method to return just the stake info.\n * @param addr - The account to query.\n */\n function _getStakeInfo(\n address addr\n ) internal view returns (StakeInfo memory info) {\n DepositInfo storage depositInfo = deposits[addr];\n info.stake = depositInfo.stake;\n info.unstakeDelaySec = depositInfo.unstakeDelaySec;\n }\n\n /// @inheritdoc IStakeManager\n function balanceOf(address account) public view returns (uint256) {\n return deposits[account].deposit;\n }\n\n receive() external payable {\n depositTo(msg.sender);\n }\n\n\n /**\n * Increments an account's deposit.\n * @param account - The account to increment.\n * @param amount - The amount to increment by.\n * @return the updated deposit of this account\n */\n function _incrementDeposit(address account, uint256 amount) internal returns (uint256) {\n unchecked {\n DepositInfo storage info = deposits[account];\n uint256 newAmount = info.deposit + amount;\n info.deposit = newAmount;\n return newAmount;\n }\n }\n\n /**\n * Try to decrement the account's deposit.\n * @param account - The account to decrement.\n * @param amount - The amount to decrement by.\n * @return true if the decrement succeeded (that is, previous balance was at least that amount)\n */\n function _tryDecrementDeposit(address account, uint256 amount) internal returns(bool) {\n unchecked {\n DepositInfo storage info = deposits[account];\n uint256 currentDeposit = info.deposit;\n if (currentDeposit < amount) {\n return false;\n }\n info.deposit = currentDeposit - amount;\n return true;\n }\n }\n\n /// @inheritdoc IStakeManager\n function depositTo(address account) public virtual payable {\n uint256 newDeposit = _incrementDeposit(account, msg.value);\n emit Deposited(account, newDeposit);\n }\n\n /// @inheritdoc IStakeManager\n function addStake(uint32 unstakeDelaySec) external payable {\n DepositInfo storage info = deposits[msg.sender];\n require(unstakeDelaySec > 0, \"must specify unstake delay\");\n require(\n unstakeDelaySec >= info.unstakeDelaySec,\n \"cannot decrease unstake time\"\n );\n uint256 stake = info.stake + msg.value;\n require(stake > 0, \"no stake specified\");\n require(stake <= type(uint112).max, \"stake overflow\");\n deposits[msg.sender] = DepositInfo(\n info.deposit,\n true,\n uint112(stake),\n unstakeDelaySec,\n 0\n );\n emit StakeLocked(msg.sender, stake, unstakeDelaySec);\n }\n\n /// @inheritdoc IStakeManager\n function unlockStake() external {\n DepositInfo storage info = deposits[msg.sender];\n require(info.unstakeDelaySec != 0, \"not staked\");\n require(info.staked, \"already unstaking\");\n uint48 withdrawTime = uint48(block.timestamp) + info.unstakeDelaySec;\n info.withdrawTime = withdrawTime;\n info.staked = false;\n emit StakeUnlocked(msg.sender, withdrawTime);\n }\n\n /// @inheritdoc IStakeManager\n function withdrawStake(address payable withdrawAddress) external {\n DepositInfo storage info = deposits[msg.sender];\n uint256 stake = info.stake;\n require(stake > 0, \"No stake to withdraw\");\n require(info.withdrawTime > 0, \"must call unlockStake() first\");\n require(\n info.withdrawTime <= block.timestamp,\n \"Stake withdrawal is not due\"\n );\n info.unstakeDelaySec = 0;\n info.withdrawTime = 0;\n info.stake = 0;\n emit StakeWithdrawn(msg.sender, withdrawAddress, stake);\n (bool success,) = withdrawAddress.call{value: stake}(\"\");\n require(success, \"failed to withdraw stake\");\n }\n\n /// @inheritdoc IStakeManager\n function withdrawTo(\n address payable withdrawAddress,\n uint256 withdrawAmount\n ) external {\n DepositInfo storage info = deposits[msg.sender];\n uint256 currentDeposit = info.deposit;\n require(withdrawAmount <= currentDeposit, \"Withdraw amount too large\");\n info.deposit = currentDeposit - withdrawAmount;\n emit Withdrawn(msg.sender, withdrawAddress, withdrawAmount);\n (bool success,) = withdrawAddress.call{value: withdrawAmount}(\"\");\n require(success, \"failed to withdraw\");\n }\n}\n" + }, + "contracts/core/UserOperationLib.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.28;\n\n/* solhint-disable no-inline-assembly */\n\nimport \"../interfaces/PackedUserOperation.sol\";\nimport {calldataKeccak, min} from \"./Helpers.sol\";\n\n/**\n * Utility functions helpful when working with UserOperation structs.\n */\nlibrary UserOperationLib {\n\n uint256 public constant PAYMASTER_VALIDATION_GAS_OFFSET = 20;\n uint256 public constant PAYMASTER_POSTOP_GAS_OFFSET = 36;\n uint256 public constant PAYMASTER_DATA_OFFSET = 52;\n\n /**\n * Relayer/block builder might submit the TX with higher priorityFee,\n * but the user should not pay above what he signed for.\n * @param userOp - The user operation data.\n */\n function gasPrice(\n PackedUserOperation calldata userOp\n ) internal view returns (uint256) {\n unchecked {\n (uint256 maxPriorityFeePerGas, uint256 maxFeePerGas) = unpackUints(userOp.gasFees);\n return min(maxFeePerGas, maxPriorityFeePerGas + block.basefee);\n }\n }\n\n bytes32 internal constant PACKED_USEROP_TYPEHASH =\n keccak256(\n \"PackedUserOperation(address sender,uint256 nonce,bytes initCode,bytes callData,bytes32 accountGasLimits,uint256 preVerificationGas,bytes32 gasFees,bytes paymasterAndData)\"\n );\n\n /**\n * Pack the user operation data into bytes for hashing.\n * @param userOp - The user operation data.\n * @param overrideInitCodeHash - If set, encode this instead of the initCode field in the userOp.\n */\n function encode(\n PackedUserOperation calldata userOp,\n bytes32 overrideInitCodeHash\n ) internal pure returns (bytes memory ret) {\n address sender = userOp.sender;\n uint256 nonce = userOp.nonce;\n bytes32 hashInitCode = overrideInitCodeHash != 0 ? overrideInitCodeHash : calldataKeccak(userOp.initCode);\n bytes32 hashCallData = calldataKeccak(userOp.callData);\n bytes32 accountGasLimits = userOp.accountGasLimits;\n uint256 preVerificationGas = userOp.preVerificationGas;\n bytes32 gasFees = userOp.gasFees;\n bytes32 hashPaymasterAndData = calldataKeccak(userOp.paymasterAndData);\n\n return abi.encode(\n UserOperationLib.PACKED_USEROP_TYPEHASH,\n sender, nonce,\n hashInitCode, hashCallData,\n accountGasLimits, preVerificationGas, gasFees,\n hashPaymasterAndData\n );\n }\n\n function unpackUints(\n bytes32 packed\n ) internal pure returns (uint256 high128, uint256 low128) {\n return (unpackHigh128(packed), unpackLow128(packed));\n }\n\n // Unpack just the high 128-bits from a packed value\n function unpackHigh128(bytes32 packed) internal pure returns (uint256) {\n return uint256(packed) >> 128;\n }\n\n // Unpack just the low 128-bits from a packed value\n function unpackLow128(bytes32 packed) internal pure returns (uint256) {\n return uint128(uint256(packed));\n }\n\n function unpackMaxPriorityFeePerGas(PackedUserOperation calldata userOp)\n internal pure returns (uint256) {\n return unpackHigh128(userOp.gasFees);\n }\n\n function unpackMaxFeePerGas(PackedUserOperation calldata userOp)\n internal pure returns (uint256) {\n return unpackLow128(userOp.gasFees);\n }\n\n function unpackVerificationGasLimit(PackedUserOperation calldata userOp)\n internal pure returns (uint256) {\n return unpackHigh128(userOp.accountGasLimits);\n }\n\n function unpackCallGasLimit(PackedUserOperation calldata userOp)\n internal pure returns (uint256) {\n return unpackLow128(userOp.accountGasLimits);\n }\n\n function unpackPaymasterVerificationGasLimit(PackedUserOperation calldata userOp)\n internal pure returns (uint256) {\n return uint128(bytes16(userOp.paymasterAndData[PAYMASTER_VALIDATION_GAS_OFFSET : PAYMASTER_POSTOP_GAS_OFFSET]));\n }\n\n function unpackPostOpGasLimit(PackedUserOperation calldata userOp)\n internal pure returns (uint256) {\n return uint128(bytes16(userOp.paymasterAndData[PAYMASTER_POSTOP_GAS_OFFSET : PAYMASTER_DATA_OFFSET]));\n }\n\n function unpackPaymasterStaticFields(\n bytes calldata paymasterAndData\n ) internal pure returns (address paymaster, uint256 validationGasLimit, uint256 postOpGasLimit) {\n return (\n address(bytes20(paymasterAndData[: PAYMASTER_VALIDATION_GAS_OFFSET])),\n uint128(bytes16(paymasterAndData[PAYMASTER_VALIDATION_GAS_OFFSET : PAYMASTER_POSTOP_GAS_OFFSET])),\n uint128(bytes16(paymasterAndData[PAYMASTER_POSTOP_GAS_OFFSET : PAYMASTER_DATA_OFFSET]))\n );\n }\n\n /**\n * Hash the user operation data.\n * @param userOp - The user operation data.\n * @param overrideInitCodeHash - If set, the initCode hash will be replaced with this value just for UserOp hashing.\n */\n function hash(\n PackedUserOperation calldata userOp,\n bytes32 overrideInitCodeHash\n ) internal pure returns (bytes32) {\n return keccak256(encode(userOp, overrideInitCodeHash));\n }\n}\n" + }, + "contracts/interfaces/IAccount.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.28;\n\nimport \"./PackedUserOperation.sol\";\n\ninterface IAccount {\n /**\n * Validate user's signature and nonce\n * the entryPoint will make the call to the recipient only if this validation call returns successfully.\n * signature failure should be reported by returning SIG_VALIDATION_FAILED (1).\n * This allows making a \"simulation call\" without a valid signature\n * Other failures (e.g. nonce mismatch, or invalid signature format) should still revert to signal failure.\n *\n * @dev Must validate caller is the entryPoint.\n * Must validate the signature and nonce\n * @param userOp - The operation that is about to be executed.\n * @param userOpHash - Hash of the user's request data. can be used as the basis for signature.\n * @param missingAccountFunds - Missing funds on the account's deposit in the entrypoint.\n * This is the minimum amount to transfer to the sender(entryPoint) to be\n * able to make the call. The excess is left as a deposit in the entrypoint\n * for future calls. Can be withdrawn anytime using \"entryPoint.withdrawTo()\".\n * In case there is a paymaster in the request (or the current deposit is high\n * enough), this value will be zero.\n * @return validationData - Packaged ValidationData structure. use `_packValidationData` and\n * `_unpackValidationData` to encode and decode.\n * <20-byte> aggregatorOrSigFail - 0 for valid signature, 1 to mark signature failure,\n * otherwise, an address of an \"aggregator\" contract.\n * <6-byte> validUntil - Last timestamp this operation is valid at, or 0 for \"indefinitely\"\n * <6-byte> validAfter - First timestamp this operation is valid\n * If an account doesn't use time-range, it is enough to\n * return SIG_VALIDATION_FAILED value (1) for signature failure.\n * Note that the validation code cannot use block.timestamp (or block.number) directly.\n */\n function validateUserOp(\n PackedUserOperation calldata userOp,\n bytes32 userOpHash,\n uint256 missingAccountFunds\n ) external returns (uint256 validationData);\n}\n" + }, + "contracts/interfaces/IAccountExecute.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.28;\n\nimport \"./PackedUserOperation.sol\";\n\ninterface IAccountExecute {\n /**\n * Account may implement this execute method.\n * passing this methodSig at the beginning of callData will cause the entryPoint to pass the full UserOp (and hash)\n * to the account.\n * The account should skip the methodSig, and use the callData (and optionally, other UserOp fields)\n *\n * @param userOp - The operation that was just validated.\n * @param userOpHash - Hash of the user's request data.\n */\n function executeUserOp(\n PackedUserOperation calldata userOp,\n bytes32 userOpHash\n ) external;\n}\n" + }, + "contracts/interfaces/IAggregator.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.28;\n\nimport \"./PackedUserOperation.sol\";\n\n/**\n * Aggregated Signatures validator.\n */\ninterface IAggregator {\n /**\n * Validate an aggregated signature.\n * Reverts if the aggregated signature does not match the given list of operations.\n * @param userOps - An array of UserOperations to validate the signature for.\n * @param signature - The aggregated signature.\n */\n function validateSignatures(\n PackedUserOperation[] calldata userOps,\n bytes calldata signature\n ) external;\n\n /**\n * Validate the signature of a single userOp.\n * This method should be called by bundler after EntryPointSimulation.simulateValidation() returns\n * the aggregator this account uses.\n * First it validates the signature over the userOp. Then it returns data to be used when creating the handleOps.\n * @param userOp - The userOperation received from the user.\n * @return sigForUserOp - The value to put into the signature field of the userOp when calling handleOps.\n * (usually empty, unless account and aggregator support some kind of \"multisig\".\n */\n function validateUserOpSignature(\n PackedUserOperation calldata userOp\n ) external view returns (bytes memory sigForUserOp);\n\n /**\n * Aggregate multiple signatures into a single value.\n * This method is called off-chain to calculate the signature to pass with handleOps()\n * bundler MAY use optimized custom code to perform this aggregation.\n * @param userOps - An array of UserOperations to collect the signatures from.\n * @return aggregatedSignature - The aggregated signature.\n */\n function aggregateSignatures(\n PackedUserOperation[] calldata userOps\n ) external view returns (bytes memory aggregatedSignature);\n}\n" + }, + "contracts/interfaces/IEntryPoint.sol": { + "content": "/**\n ** Account-Abstraction (EIP-4337) singleton EntryPoint implementation.\n ** Only one instance required on each chain.\n **/\n// SPDX-License-Identifier: MIT\npragma solidity ^0.8.28;\n\n/* solhint-disable avoid-low-level-calls */\n/* solhint-disable no-inline-assembly */\n/* solhint-disable reason-string */\n\nimport \"./PackedUserOperation.sol\";\nimport \"./IStakeManager.sol\";\nimport \"./IAggregator.sol\";\nimport \"./INonceManager.sol\";\nimport \"./ISenderCreator.sol\";\n\ninterface IEntryPoint is IStakeManager, INonceManager {\n /***\n * An event emitted after each successful request.\n * @param userOpHash - Unique identifier for the request (hash its entire content, except signature).\n * @param sender - The account that generates this request.\n * @param paymaster - If non-null, the paymaster that pays for this request.\n * @param nonce - The nonce value from the request.\n * @param success - True if the sender transaction succeeded, false if reverted.\n * @param actualGasCost - Actual amount paid (by account or paymaster) for this UserOperation.\n * @param actualGasUsed - Total gas used by this UserOperation (including preVerification, creation,\n * validation and execution).\n */\n event UserOperationEvent(\n bytes32 indexed userOpHash,\n address indexed sender,\n address indexed paymaster,\n uint256 nonce,\n bool success,\n uint256 actualGasCost,\n uint256 actualGasUsed\n );\n\n /**\n * Account \"sender\" was deployed.\n * @param userOpHash - The userOp that deployed this account. UserOperationEvent will follow.\n * @param sender - The account that is deployed\n * @param factory - The factory used to deploy this account (in the initCode)\n * @param paymaster - The paymaster used by this UserOp\n */\n event AccountDeployed(\n bytes32 indexed userOpHash,\n address indexed sender,\n address factory,\n address paymaster\n );\n\n /**\n * An event emitted if the UserOperation \"callData\" reverted with non-zero length.\n * @param userOpHash - The request unique identifier.\n * @param sender - The sender of this request.\n * @param nonce - The nonce used in the request.\n * @param revertReason - The return bytes from the reverted \"callData\" call.\n */\n event UserOperationRevertReason(\n bytes32 indexed userOpHash,\n address indexed sender,\n uint256 nonce,\n bytes revertReason\n );\n\n /**\n * An event emitted if the UserOperation Paymaster's \"postOp\" call reverted with non-zero length.\n * @param userOpHash - The request unique identifier.\n * @param sender - The sender of this request.\n * @param nonce - The nonce used in the request.\n * @param revertReason - The return bytes from the reverted call to \"postOp\".\n */\n event PostOpRevertReason(\n bytes32 indexed userOpHash,\n address indexed sender,\n uint256 nonce,\n bytes revertReason\n );\n\n /**\n * UserOp consumed more than prefund. The UserOperation is reverted, and no refund is made.\n * @param userOpHash - The request unique identifier.\n * @param sender - The sender of this request.\n * @param nonce - The nonce used in the request.\n */\n event UserOperationPrefundTooLow(\n bytes32 indexed userOpHash,\n address indexed sender,\n uint256 nonce\n );\n\n /**\n * An event emitted by handleOps() and handleAggregatedOps(), before starting the execution loop.\n * Any event emitted before this event, is part of the validation.\n */\n event BeforeExecution();\n\n /**\n * Signature aggregator used by the following UserOperationEvents within this bundle.\n * @param aggregator - The aggregator used for the following UserOperationEvents.\n */\n event SignatureAggregatorChanged(address indexed aggregator);\n\n /**\n * A custom revert error of handleOps andhandleAggregatedOps, to identify the offending op.\n * Should be caught in off-chain handleOps/handleAggregatedOps simulation and not happen on-chain.\n * Useful for mitigating DoS attempts against batchers or for troubleshooting of factory/account/paymaster reverts.\n * NOTE: If simulateValidation passes successfully, there should be no reason for handleOps to fail on it.\n * @param opIndex - Index into the array of ops to the failed one (in simulateValidation, this is always zero).\n * @param reason - Revert reason. The string starts with a unique code \"AAmn\",\n * where \"m\" is \"1\" for factory, \"2\" for account and \"3\" for paymaster issues,\n * so a failure can be attributed to the correct entity.\n */\n error FailedOp(uint256 opIndex, string reason);\n\n /**\n * A custom revert error of handleOps and handleAggregatedOps, to report a revert by account or paymaster.\n * @param opIndex - Index into the array of ops to the failed one (in simulateValidation, this is always zero).\n * @param reason - Revert reason. see FailedOp(uint256,string), above\n * @param inner - data from inner cought revert reason\n * @dev note that inner is truncated to 2048 bytes\n */\n error FailedOpWithRevert(uint256 opIndex, string reason, bytes inner);\n\n error PostOpReverted(bytes returnData);\n\n /**\n * Error case when a signature aggregator fails to verify the aggregated signature it had created.\n * @param aggregator The aggregator that failed to verify the signature\n */\n error SignatureValidationFailed(address aggregator);\n\n // Return value of getSenderAddress.\n error SenderAddressResult(address sender);\n\n // UserOps handled, per aggregator.\n struct UserOpsPerAggregator {\n PackedUserOperation[] userOps;\n // Aggregator address\n IAggregator aggregator;\n // Aggregated signature\n bytes signature;\n }\n\n /**\n * Execute a batch of UserOperations.\n * No signature aggregator is used.\n * If any account requires an aggregator (that is, it returned an aggregator when\n * performing simulateValidation), then handleAggregatedOps() must be used instead.\n * @param ops - The operations to execute.\n * @param beneficiary - The address to receive the fees.\n */\n function handleOps(\n PackedUserOperation[] calldata ops,\n address payable beneficiary\n ) external;\n\n /**\n * Execute a batch of UserOperation with Aggregators\n * @param opsPerAggregator - The operations to execute, grouped by aggregator (or address(0) for no-aggregator accounts).\n * @param beneficiary - The address to receive the fees.\n */\n function handleAggregatedOps(\n UserOpsPerAggregator[] calldata opsPerAggregator,\n address payable beneficiary\n ) external;\n\n /**\n * Generate a request Id - unique identifier for this request.\n * The request ID is a hash over the content of the userOp (except the signature), entrypoint address, chainId and (optionally) 7702 delegate address\n * @param userOp - The user operation to generate the request ID for.\n * @return hash the hash of this UserOperation\n */\n function getUserOpHash(\n PackedUserOperation calldata userOp\n ) external view returns (bytes32);\n\n /**\n * Gas and return values during simulation.\n * @param preOpGas - The gas used for validation (including preValidationGas)\n * @param prefund - The required prefund for this operation\n * @param accountValidationData - returned validationData from account.\n * @param paymasterValidationData - return validationData from paymaster.\n * @param paymasterContext - Returned by validatePaymasterUserOp (to be passed into postOp)\n */\n struct ReturnInfo {\n uint256 preOpGas;\n uint256 prefund;\n uint256 accountValidationData;\n uint256 paymasterValidationData;\n bytes paymasterContext;\n }\n\n /**\n * Get counterfactual sender address.\n * Calculate the sender contract address that will be generated by the initCode and salt in the UserOperation.\n * This method always revert, and returns the address in SenderAddressResult error.\n * @notice this method cannot be used for EIP-7702 derived contracts.\n *\n * @param initCode - The constructor code to be passed into the UserOperation.\n */\n function getSenderAddress(bytes memory initCode) external;\n\n error DelegateAndRevert(bool success, bytes ret);\n\n /**\n * Helper method for dry-run testing.\n * @dev calling this method, the EntryPoint will make a delegatecall to the given data, and report (via revert) the result.\n * The method always revert, so is only useful off-chain for dry run calls, in cases where state-override to replace\n * actual EntryPoint code is less convenient.\n * @param target a target contract to make a delegatecall from entrypoint\n * @param data data to pass to target in a delegatecall\n */\n function delegateAndRevert(address target, bytes calldata data) external;\n\n /**\n * @notice Retrieves the immutable SenderCreator contract which is responsible for deployment of sender contracts.\n */\n function senderCreator() external view returns (ISenderCreator);\n}\n" + }, + "contracts/interfaces/INonceManager.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.28;\n\ninterface INonceManager {\n\n /**\n * Return the next nonce for this sender.\n * Within a given key, the nonce values are sequenced (starting with zero, and incremented by one on each userop)\n * But UserOp with different keys can come with arbitrary order.\n *\n * @param sender the account address\n * @param key the high 192 bit of the nonce\n * @return nonce a full nonce to pass for next UserOp with this sender.\n */\n function getNonce(address sender, uint192 key)\n external view returns (uint256 nonce);\n\n /**\n * Manually increment the nonce of the sender.\n * This method is exposed just for completeness..\n * Account does NOT need to call it, neither during validation, nor elsewhere,\n * as the EntryPoint will update the nonce regardless.\n * Possible use-case is call it with various keys to \"initialize\" their nonces to one, so that future\n * UserOperations will not pay extra for the first transaction with a given key.\n *\n * @param key - the \"nonce key\" to increment the \"nonce sequence\" for.\n */\n function incrementNonce(uint192 key) external;\n}\n" + }, + "contracts/interfaces/IPaymaster.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.28;\n\nimport \"./PackedUserOperation.sol\";\n\n/**\n * The interface exposed by a paymaster contract, who agrees to pay the gas for user's operations.\n * A paymaster must hold a stake to cover the required entrypoint stake and also the gas for the transaction.\n */\ninterface IPaymaster {\n enum PostOpMode {\n // User op succeeded.\n opSucceeded,\n // User op reverted. Still has to pay for gas.\n opReverted,\n // Only used internally in the EntryPoint (cleanup after postOp reverts). Never calling paymaster with this value\n postOpReverted\n }\n\n /**\n * Payment validation: check if paymaster agrees to pay.\n * Must verify sender is the entryPoint.\n * Revert to reject this request.\n * Note that bundlers will reject this method if it changes the state, unless the paymaster is trusted (whitelisted).\n * The paymaster pre-pays using its deposit, and receive back a refund after the postOp method returns.\n * @param userOp - The user operation.\n * @param userOpHash - Hash of the user's request data.\n * @param maxCost - The maximum cost of this transaction (based on maximum gas and gas price from userOp).\n * @return context - Value to send to a postOp. Zero length to signify postOp is not required.\n * @return validationData - Signature and time-range of this operation, encoded the same as the return\n * value of validateUserOperation.\n * <20-byte> aggregatorOrSigFail - 0 for valid signature, 1 to mark signature failure,\n * other values are invalid for paymaster.\n * <6-byte> validUntil - Last timestamp this operation is valid at, or 0 for \"indefinitely\"\n * <6-byte> validAfter - first timestamp this operation is valid\n * Note that the validation code cannot use block.timestamp (or block.number) directly.\n */\n function validatePaymasterUserOp(\n PackedUserOperation calldata userOp,\n bytes32 userOpHash,\n uint256 maxCost\n ) external returns (bytes memory context, uint256 validationData);\n\n /**\n * Post-operation handler.\n * Must verify sender is the entryPoint.\n * @param mode - Enum with the following options:\n * opSucceeded - User operation succeeded.\n * opReverted - User op reverted. The paymaster still has to pay for gas.\n * postOpReverted - never passed in a call to postOp().\n * @param context - The context value returned by validatePaymasterUserOp\n * @param actualGasCost - Actual cost of gas used so far (without this postOp call).\n * @param actualUserOpFeePerGas - the gas price this UserOp pays. This value is based on the UserOp's maxFeePerGas\n * and maxPriorityFee (and basefee)\n * It is not the same as tx.gasprice, which is what the bundler pays.\n */\n function postOp(\n PostOpMode mode,\n bytes calldata context,\n uint256 actualGasCost,\n uint256 actualUserOpFeePerGas\n ) external;\n}\n" + }, + "contracts/interfaces/ISenderCreator.sol": { + "content": "\n// SPDX-License-Identifier: MIT\npragma solidity ^0.8.28;\n\ninterface ISenderCreator {\n /**\n * @dev Creates a new sender contract.\n * @return sender Address of the newly created sender contract.\n */\n function createSender(bytes calldata initCode) external returns (address sender);\n\n /**\n * Use initCallData to initialize an EIP-7702 account.\n * The caller is the EntryPoint contract and it is already verified to be an EIP-7702 account.\n * Note: Can be called multiple times as long as an appropriate initCode is supplied\n *\n * @param sender - the 'sender' EIP-7702 account to be initialized.\n * @param initCallData - the call data to be passed to the sender account call.\n */\n function initEip7702Sender(address sender, bytes calldata initCallData) external;\n}\n" + }, + "contracts/interfaces/IStakeManager.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.28;\n\n/**\n * Manage deposits and stakes.\n * Deposit is just a balance used to pay for UserOperations (either by a paymaster or an account).\n * Stake is value locked for at least \"unstakeDelay\" by the staked entity.\n */\ninterface IStakeManager {\n event Deposited(address indexed account, uint256 totalDeposit);\n\n event Withdrawn(\n address indexed account,\n address withdrawAddress,\n uint256 amount\n );\n\n // Emitted when stake or unstake delay are modified.\n event StakeLocked(\n address indexed account,\n uint256 totalStaked,\n uint256 unstakeDelaySec\n );\n\n // Emitted once a stake is scheduled for withdrawal.\n event StakeUnlocked(address indexed account, uint256 withdrawTime);\n\n event StakeWithdrawn(\n address indexed account,\n address withdrawAddress,\n uint256 amount\n );\n\n /**\n * @param deposit - The entity's deposit.\n * @param staked - True if this entity is staked.\n * @param stake - Actual amount of ether staked for this entity.\n * @param unstakeDelaySec - Minimum delay to withdraw the stake.\n * @param withdrawTime - First block timestamp where 'withdrawStake' will be callable, or zero if already locked.\n * @dev Sizes were chosen so that deposit fits into one cell (used during handleOp)\n * and the rest fit into a 2nd cell (used during stake/unstake)\n * - 112 bit allows for 10^15 eth\n * - 48 bit for full timestamp\n * - 32 bit allows 150 years for unstake delay\n */\n struct DepositInfo {\n uint256 deposit;\n bool staked;\n uint112 stake;\n uint32 unstakeDelaySec;\n uint48 withdrawTime;\n }\n\n // API struct used by getStakeInfo and simulateValidation.\n struct StakeInfo {\n uint256 stake;\n uint256 unstakeDelaySec;\n }\n\n /**\n * Get deposit info.\n * @param account - The account to query.\n * @return info - Full deposit information of given account.\n */\n function getDepositInfo(\n address account\n ) external view returns (DepositInfo memory info);\n\n /**\n * Get account balance.\n * @param account - The account to query.\n * @return - The deposit (for gas payment) of the account.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * Add to the deposit of the given account.\n * @param account - The account to add to.\n */\n function depositTo(address account) external payable;\n\n /**\n * Add to the account's stake - amount and delay\n * any pending unstake is first cancelled.\n * @param unstakeDelaySec - The new lock duration before the deposit can be withdrawn.\n */\n function addStake(uint32 unstakeDelaySec) external payable;\n\n /**\n * Attempt to unlock the stake.\n * The value can be withdrawn (using withdrawStake) after the unstake delay.\n */\n function unlockStake() external;\n\n /**\n * Withdraw from the (unlocked) stake.\n * Must first call unlockStake and wait for the unstakeDelay to pass.\n * @param withdrawAddress - The address to send withdrawn value.\n */\n function withdrawStake(address payable withdrawAddress) external;\n\n /**\n * Withdraw from the deposit.\n * @param withdrawAddress - The address to send withdrawn value.\n * @param withdrawAmount - The amount to withdraw.\n */\n function withdrawTo(\n address payable withdrawAddress,\n uint256 withdrawAmount\n ) external;\n}\n" + }, + "contracts/interfaces/PackedUserOperation.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.28;\n\n/**\n * User Operation struct\n * @param sender - The sender account of this request.\n * @param nonce - Unique value the sender uses to verify it is not a replay.\n * @param initCode - If set, the account contract will be created by this constructor\n * @param callData - The method call to execute on this account.\n * @param accountGasLimits - Packed gas limits for validateUserOp and gas limit passed to the callData method call.\n * @param preVerificationGas - Gas not calculated by the handleOps method, but added to the gas paid.\n * Covers batch overhead.\n * @param gasFees - packed gas fields maxPriorityFeePerGas and maxFeePerGas - Same as EIP-1559 gas parameters.\n * @param paymasterAndData - If set, this field holds the paymaster address, verification gas limit, postOp gas limit and paymaster-specific extra data\n * The paymaster will pay for the transaction instead of the sender.\n * @param signature - Sender-verified signature over the entire request, the EntryPoint address and the chain ID.\n */\nstruct PackedUserOperation {\n address sender;\n uint256 nonce;\n bytes initCode;\n bytes callData;\n bytes32 accountGasLimits;\n uint256 preVerificationGas;\n bytes32 gasFees;\n bytes paymasterAndData;\n bytes signature;\n}\n" + }, + "contracts/utils/Exec.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.28;\n\n// solhint-disable no-inline-assembly\n\n/**\n * Utility functions helpful when making different kinds of contract calls in Solidity.\n */\nlibrary Exec {\n\n function call(\n address to,\n uint256 value,\n bytes memory data,\n uint256 txGas\n ) internal returns (bool success) {\n assembly (\"memory-safe\") {\n success := call(txGas, to, value, add(data, 0x20), mload(data), 0, 0)\n }\n }\n\n function staticcall(\n address to,\n bytes memory data,\n uint256 txGas\n ) internal view returns (bool success) {\n assembly (\"memory-safe\") {\n success := staticcall(txGas, to, add(data, 0x20), mload(data), 0, 0)\n }\n }\n\n function delegateCall(\n address to,\n bytes memory data,\n uint256 txGas\n ) internal returns (bool success) {\n assembly (\"memory-safe\") {\n success := delegatecall(txGas, to, add(data, 0x20), mload(data), 0, 0)\n }\n }\n\n // get returned data from last call or delegateCall\n // maxLen - maximum length of data to return, or zero, for the full length\n function getReturnData(uint256 maxLen) internal pure returns (bytes memory returnData) {\n assembly (\"memory-safe\") {\n let len := returndatasize()\n if gt(maxLen,0) {\n if gt(len, maxLen) {\n len := maxLen\n }\n }\n let ptr := mload(0x40)\n mstore(0x40, add(ptr, add(len, 0x20)))\n mstore(ptr, len)\n returndatacopy(add(ptr, 0x20), 0, len)\n returnData := ptr\n }\n }\n\n // revert with explicit byte array (probably reverted info from call)\n function revertWithData(bytes memory returnData) internal pure {\n assembly (\"memory-safe\") {\n revert(add(returnData, 32), mload(returnData))\n }\n }\n\n // Propagate revert data from last call\n function revertWithReturnData() internal pure {\n revertWithData(getReturnData(0));\n }\n}\n" + } + }, + "settings": { + "evmVersion": "cancun", + "optimizer": { + "enabled": true, + "runs": 1000000 + }, + "viaIR": true, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata" + ], + "": [ + "ast" + ] + } + } + } +} \ No newline at end of file diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/funding.json b/dependencies/eth-infinitism-account-abstraction-0.8.0/funding.json new file mode 100644 index 00000000..4dca7efe --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/funding.json @@ -0,0 +1,5 @@ +{ + "opRetro": { + "projectId": "0xb98778ca9ff41446e2bc304f7b5d27f0fa7c2bcd11df19e22d1352c06698a1f6" + } +} diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/gascalc/0-init-gas-checker.ts b/dependencies/eth-infinitism-account-abstraction-0.8.0/gascalc/0-init-gas-checker.ts new file mode 100644 index 00000000..78d6b7fc --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/gascalc/0-init-gas-checker.ts @@ -0,0 +1,12 @@ +import { GasCheckCollector, GasChecker } from './GasChecker' + +describe('gas calculations', function () { + this.timeout(60000) + const g = new GasChecker() + + it('warmup', async function () { + await GasCheckCollector.init() + // dummy run - first run is slower. + await g.runTest({ title: 'simple', count: 1, diffLastGas: false }) + }) +}) diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/gascalc/1-simple-wallet.gas.ts b/dependencies/eth-infinitism-account-abstraction-0.8.0/gascalc/1-simple-wallet.gas.ts new file mode 100644 index 00000000..0943d1f0 --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/gascalc/1-simple-wallet.gas.ts @@ -0,0 +1,17 @@ +import { GasChecker } from './GasChecker' + +context('simple account', function () { + this.timeout(60000) + const g = new GasChecker() + + it('simple 1', async function () { + await g.addTestRow({ title: 'simple', count: 1, diffLastGas: false }) + await g.addTestRow({ title: 'simple - diff from previous', count: 2, diffLastGas: true }) + }) + + it('simple 10', async function () { + if (g.skipLong()) this.skip() + await g.addTestRow({ title: 'simple', count: 10, diffLastGas: false }) + await g.addTestRow({ title: 'simple - diff from previous', count: 11, diffLastGas: true }) + }) +}) diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/gascalc/2-paymaster.gas.ts b/dependencies/eth-infinitism-account-abstraction-0.8.0/gascalc/2-paymaster.gas.ts new file mode 100644 index 00000000..89a5d3dc --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/gascalc/2-paymaster.gas.ts @@ -0,0 +1,43 @@ +import { parseEther } from 'ethers/lib/utils' +import { TestPaymasterAcceptAll__factory } from '../typechain' +import { ethers } from 'hardhat' +import { GasChecker } from './GasChecker' +import { Create2Factory } from '../src/Create2Factory' +import { hexValue } from '@ethersproject/bytes' + +const ethersSigner = ethers.provider.getSigner() + +context('Minimal Paymaster', function () { + this.timeout(60000) + const g = new GasChecker() + + let paymasterAddress: string + before(async () => { + const paymasterInit = hexValue(new TestPaymasterAcceptAll__factory(ethersSigner).getDeployTransaction(g.entryPoint().address).data!) + paymasterAddress = await new Create2Factory(ethers.provider, ethersSigner).deploy(paymasterInit, 0) + const paymaster = TestPaymasterAcceptAll__factory.connect(paymasterAddress, ethersSigner) + await paymaster.addStake(1, { value: 1 }) + await g.entryPoint().depositTo(paymaster.address, { value: parseEther('10') }) + }) + it('simple paymaster', async function () { + await g.addTestRow({ title: 'simple paymaster', count: 1, paymaster: paymasterAddress, diffLastGas: false }) + await g.addTestRow({ + title: 'simple paymaster with diff', + count: 2, + paymaster: paymasterAddress, + diffLastGas: true + }) + }) + + it('simple paymaster 10', async function () { + if (g.skipLong()) this.skip() + + await g.addTestRow({ title: 'simple paymaster', count: 10, paymaster: paymasterAddress, diffLastGas: false }) + await g.addTestRow({ + title: 'simple paymaster with diff', + count: 11, + paymaster: paymasterAddress, + diffLastGas: true + }) + }) +}) diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/gascalc/3-huge-tx-gas.ts b/dependencies/eth-infinitism-account-abstraction-0.8.0/gascalc/3-huge-tx-gas.ts new file mode 100644 index 00000000..ae762478 --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/gascalc/3-huge-tx-gas.ts @@ -0,0 +1,17 @@ +import { DefaultGasTestInfo, GasChecker } from './GasChecker' + +context('huge tx - 5k', function () { + this.timeout(60000) + const huge = DefaultGasTestInfo.destCallData!.padEnd(10240, 'f') + const g = new GasChecker() + + it('big tx 5k', async () => { + await g.addTestRow({ title: 'big tx 5k', count: 1, destCallData: huge, diffLastGas: false }) + await g.addTestRow({ title: 'big tx - diff from previous', count: 2, destCallData: huge, diffLastGas: true }) + }) + it('big tx 10', async function () { + if (g.skipLong()) this.skip() + await g.addTestRow({ title: 'big tx 5k', count: 10, destCallData: huge, diffLastGas: false }) + await g.addTestRow({ title: 'big tx - diff from previous', count: 11, destCallData: huge, diffLastGas: true }) + }) +}) diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/gascalc/4-paymaster-postop.gas.ts b/dependencies/eth-infinitism-account-abstraction-0.8.0/gascalc/4-paymaster-postop.gas.ts new file mode 100644 index 00000000..3b44bafc --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/gascalc/4-paymaster-postop.gas.ts @@ -0,0 +1,45 @@ +import { parseEther } from 'ethers/lib/utils' +import { GasCalcPaymasterWithPostOp__factory } from '../typechain' +import { ethers } from 'hardhat' +import { GasChecker } from './GasChecker' +import { Create2Factory } from '../src/Create2Factory' +import { hexValue } from '@ethersproject/bytes' + +const ethersSigner = ethers.provider.getSigner() + +context('Paymaster with PostOp', function () { + this.timeout(60000) + const g = new GasChecker() + + let paymasterAddress: string + + before(async () => { + const paymasterInit = hexValue(new GasCalcPaymasterWithPostOp__factory(ethersSigner).getDeployTransaction(g.entryPoint().address).data!) + paymasterAddress = await new Create2Factory(ethers.provider, ethersSigner).deploy(paymasterInit, 0) + const paymaster = GasCalcPaymasterWithPostOp__factory.connect(paymasterAddress, ethersSigner) + await paymaster.addStake(1, { value: 1 }) + await g.entryPoint().depositTo(paymaster.address, { value: parseEther('10') }) + }) + + it('paymaster with PostOp', async function () { + await g.addTestRow({ title: 'paymaster+postOp', count: 1, paymaster: paymasterAddress, diffLastGas: false }) + await g.addTestRow({ + title: 'paymaster+postOp with diff', + count: 2, + paymaster: paymasterAddress, + diffLastGas: true + }) + }) + + it('paymaster with postOp 10', async function () { + if (g.skipLong()) this.skip() + + await g.addTestRow({ title: 'paymaster+postOp', count: 10, paymaster: paymasterAddress, diffLastGas: false }) + await g.addTestRow({ + title: 'paymaster+postOp with diff', + count: 11, + paymaster: paymasterAddress, + diffLastGas: true + }) + }) +}) diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/gascalc/GasChecker.ts b/dependencies/eth-infinitism-account-abstraction-0.8.0/gascalc/GasChecker.ts new file mode 100644 index 00000000..6ec53ba0 --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/gascalc/GasChecker.ts @@ -0,0 +1,424 @@ +// calculate gas usage of different bundle sizes +import '../test/aa.init' +import { defaultAbiCoder, hexConcat, parseEther } from 'ethers/lib/utils' +import { + AddressZero, + createAddress, + createAccountOwner, + deployEntryPoint, decodeRevertReason +} from '../test/testutils' +import { + EntryPoint, EntryPoint__factory, SimpleAccountFactory, + SimpleAccountFactory__factory, SimpleAccount__factory +} from '../typechain' +import { BigNumberish, Wallet } from 'ethers' +import hre from 'hardhat' +import { fillSignAndPack, fillUserOp, packUserOp, signUserOp } from '../test/UserOp' +import { TransactionReceipt } from '@ethersproject/abstract-provider' +import { table, TableUserConfig } from 'table' +import { Create2Factory } from '../src/Create2Factory' +import * as fs from 'fs' +import { SimpleAccountInterface } from '../typechain/contracts/accounts/SimpleAccount' +import { PackedUserOperation } from '../test/UserOperation' +import { expect } from 'chai' +import Debug from 'debug' + +const debug = Debug('aa.gascheck') + +const gasCheckerLogFile = './reports/gas-checker.txt' + +const ethers = hre.ethers +const provider = hre.ethers.provider +const junkWallet = Wallet.fromMnemonic('test test test test test test test test test test test junk') +const globalSigner = new Wallet(junkWallet.privateKey, provider) +let lastGasUsed: number + +const minDepositOrBalance = parseEther('0.1') + +const getBalance = hre.ethers.provider.getBalance + +function range (n: number): number[] { + return Array(n).fill(0).map((val, index) => index) +} + +interface GasTestInfo { + title: string + diffLastGas: boolean + paymaster: string + count: number + // address, or 'random' or 'self' (for account itself) + dest: string + destValue: BigNumberish + destCallData: string + beneficiary: string + gasPrice: number +} + +export const DefaultGasTestInfo: Partial = { + dest: 'self', // destination is the account itself. + destValue: parseEther('0'), + destCallData: '0xb0d691fe', // entryPoint() + gasPrice: 10e9 +} + +interface GasTestResult { + title: string + count: number + gasUsed: number // actual gas used + accountEst: number // estimateGas of the inner transaction (from EP to account) + gasDiff?: number // different from last test's gas used + receipt?: TransactionReceipt +} + +/** + * singleton contract used by all GasChecker modules ("tests") + * init() static method - + * - create the singleton the first time (or return its existing instance) + * run + */ + +// gas estimate of the "execFromSingleton" methods +// we assume a given call signature has the same gas usage +// (TODO: the estimate also depends on contract code. for test purposes, assume each contract implementation has different method signature) +// at the end of the checks, we report the gas usage of all those method calls +const gasEstimatePerExec: { [key: string]: { title: string, accountEst: number } } = {} + +/** + * helper contract to generate gas test. + * see runTest() method for "test template" info + * override for different account implementation: + * - accountInitCode() - the constructor code + * - accountExec() the account execution method. + */ +export class GasChecker { + accounts: { [account: string]: Wallet } = {} + + accountOwner: Wallet + + accountInterface: SimpleAccountInterface + private locked: boolean + + constructor () { + this.accountOwner = createAccountOwner() + this.accountInterface = SimpleAccount__factory.createInterface() + void GasCheckCollector.init() + } + + // generate the "exec" calldata for this account + accountExec (dest: string, value: BigNumberish, data: string): string { + return this.accountInterface.encodeFunctionData('execute', [dest, value, data]) + } + + // generate the account "creation code" + accountInitCode (factory: SimpleAccountFactory, salt: BigNumberish): string { + return hexConcat([ + factory.address, + factory.interface.encodeFunctionData('createAccount', [this.accountOwner.address, salt]) + ]) + } + + createdAccounts = new Set() + + /** + * create accounts up to this counter. + * make sure they all have balance. + * do nothing for account already created + * @param count + */ + async createAccounts1 (count: number): Promise { + const create2Factory = new Create2Factory(this.entryPoint().provider) + const factoryAddress = await create2Factory.deploy( + hexConcat([ + SimpleAccountFactory__factory.bytecode, + defaultAbiCoder.encode(['address'], [this.entryPoint().address]) + ]), 0, 2885201) + debug('factaddr', factoryAddress) + const fact = SimpleAccountFactory__factory.connect(factoryAddress, globalSigner) + // create accounts + const creationOps: PackedUserOperation[] = [] + for (const n of range(count)) { + const salt = n + // const initCode = this.accountInitCode(fact, salt) + + const addr = await fact.getAddress(this.accountOwner.address, salt) + + if (!this.createdAccounts.has(addr)) { + const codeSize = await provider.getCode(addr).then(code => code.length) + if (codeSize === 2) { + // explicit call to fillUseROp with no "entryPoint", to make sure we manually fill everything and + // not attempt to fill from blockchain. + const op = signUserOp(await fillUserOp({ + sender: addr, + initCode: this.accountInitCode(fact, salt), + nonce: 0, + callGasLimit: 30000, + verificationGasLimit: 1000000, + // paymasterAndData: paymaster, + preVerificationGas: 1, + maxFeePerGas: 0 + }), this.accountOwner, this.entryPoint().address, await provider.getNetwork().then(net => net.chainId)) + creationOps.push(packUserOp(op)) + } + this.createdAccounts.add(addr) + } + + this.accounts[addr] = this.accountOwner + const accountBalance = await GasCheckCollector.inst.entryPoint.balanceOf(addr) + if (accountBalance.lte(minDepositOrBalance)) { + await GasCheckCollector.inst.entryPoint.depositTo(addr, { value: minDepositOrBalance.mul(5) }) + } + } + await this.entryPoint().handleOps(creationOps, globalSigner.getAddress()) + } + + /** + * helper: run a test scenario, and add a table row + * @param params - test parameters. missing values filled in from DefaultGasTestInfo + * note that 2 important params are methods: accountExec() and accountInitCode() + */ + async addTestRow (params: Partial): Promise { + await GasCheckCollector.init() + GasCheckCollector.inst.addRow(await this.runTest(params)) + } + + /** + * run a single test scenario + * @param params - test parameters. missing values filled in from DefaultGasTestInfo + * note that 2 important params are methods: accountExec() and accountInitCode() + */ + async runTest (params: Partial): Promise { + // eslint-disable-next-line @typescript-eslint/consistent-type-assertions + const info: GasTestInfo = { ...DefaultGasTestInfo, ...params } as GasTestInfo + + debug('== running test count=', info.count) + + // fill accounts up to this code. + await this.createAccounts1(info.count) + + let accountEst: number = 0 + const userOps = await Promise.all(range(info.count) + .map(index => Object.entries(this.accounts)[index]) + .map(async ([account, accountOwner]) => { + const paymaster = info.paymaster + + let { dest, destValue, destCallData } = info + if (dest === 'self') { + dest = account + } else if (dest === 'random') { + dest = createAddress() + const destBalance = await getBalance(dest) + if (destBalance.eq(0)) { + debug('dest replenish', dest) + await globalSigner.sendTransaction({ to: dest, value: 1 }) + } + } + const accountExecFromEntryPoint = this.accountExec(dest, destValue, destCallData) + + // remove the "dest" from the key to the saved estimations + // so we have a single estimation per method. + const estimateGasKey = this.accountExec(AddressZero, destValue, destCallData) + + let est = gasEstimatePerExec[estimateGasKey] + // technically, each UserOp needs estimate - but we know they are all the same for each test. + if (est == null) { + const accountEst = (await ethers.provider.estimateGas({ + from: GasCheckCollector.inst.entryPoint.address, + to: account, + data: accountExecFromEntryPoint + })).toNumber() + est = gasEstimatePerExec[estimateGasKey] = { accountEst, title: info.title } + } + // console.debug('== account est=', accountEst.toString()) + accountEst = est.accountEst + while (this.locked) { + await new Promise(resolve => setTimeout(resolve, 1)) + } + try { + this.locked = true + + const op = await fillSignAndPack({ + sender: account, + callData: accountExecFromEntryPoint, + maxPriorityFeePerGas: info.gasPrice, + maxFeePerGas: info.gasPrice, + callGasLimit: accountEst, + verificationGasLimit: 1000000, + paymaster: paymaster, + paymasterVerificationGasLimit: 50000, + paymasterPostOpGasLimit: 50000, + preVerificationGas: 1 + }, accountOwner, GasCheckCollector.inst.entryPoint) + return op + } finally { + this.locked = false + } + })) + + const txdata = GasCheckCollector.inst.entryPoint.interface.encodeFunctionData('handleOps', [userOps, info.beneficiary]) + debug('=== encoded data=', txdata.length) + const gasEst = await GasCheckCollector.inst.entryPoint.estimateGas.handleOps( + userOps, info.beneficiary, {} + ).catch(e => { + const data = e.error?.data?.data ?? e.error?.data + if (data != null) { + const e1 = GasCheckCollector.inst.entryPoint.interface.parseError(data) + throw new Error(`${e1.name}(${e1.args?.toString()})`) + } + throw e + }) + const ret = await GasCheckCollector.inst.entryPoint.handleOps(userOps, info.beneficiary, { gasLimit: gasEst.mul(3).div(2) }) + // "ret.wait()" is dead slow without it... + for (let count = 0; count < 100; count++) { + if (await provider.getTransactionReceipt(ret.hash) != null) { + break + } + await new Promise(resolve => setTimeout(resolve, 10)) + } + const rcpt = await ret.wait() + const gasUsed = rcpt.gasUsed.toNumber() + const countSuccessOps = rcpt.events?.filter(e => e.event === 'UserOperationEvent' && e.args?.success).length + + rcpt.events?.filter(e => e.event?.match(/PostOpRevertReason|UserOperationRevertReason/)).find(e => { + throw new Error(`${e.event}(${decodeRevertReason(e.args?.revertReason)})`) + }) + // check for failure with no revert reason (e.g. OOG) + expect(countSuccessOps).to.eq(userOps.length, 'Some UserOps failed to execute (with no revert reason)') + + debug('count', info.count, 'gasUsed', gasUsed) + const gasDiff = gasUsed - lastGasUsed + if (info.diffLastGas) { + debug('\tgas diff=', gasDiff) + } + lastGasUsed = gasUsed + debug('handleOps tx.hash=', rcpt.transactionHash) + const ret1: GasTestResult = { + count: info.count, + gasUsed, + accountEst, + title: info.title + // receipt: rcpt + } + if (info.diffLastGas) { + ret1.gasDiff = gasDiff + } + debug(ret1) + return ret1 + } + + // helper methods to access the GasCheckCollector singleton + addRow (res: GasTestResult): void { + GasCheckCollector.inst.addRow(res) + } + + entryPoint (): EntryPoint { + return GasCheckCollector.inst.entryPoint + } + + skipLong (): boolean { + return process.env.SKIP_LONG != null + } +} + +export class GasCheckCollector { + static inst: GasCheckCollector + static initPromise?: Promise + + entryPoint: EntryPoint + + static async init (): Promise { + if (this.inst == null) { + if (this.initPromise == null) { + this.initPromise = new GasCheckCollector()._init() + } + this.inst = await this.initPromise + } + } + + async _init (entryPointAddressOrTest: string = 'test'): Promise { + debug('signer=', await globalSigner.getAddress()) + DefaultGasTestInfo.beneficiary = createAddress() + + if (entryPointAddressOrTest === 'test') { + this.entryPoint = await deployEntryPoint(provider) + } else { + this.entryPoint = EntryPoint__factory.connect(entryPointAddressOrTest, globalSigner) + } + + const tableHeaders = [ + 'handleOps description ', + 'count', + 'total gasUsed', + 'per UserOp gas\n(delta for\none UserOp)', + // 'account.exec()\nestimateGas', + 'per UserOp overhead\n(compared to\naccount.exec())' + ] + + this.initTable(tableHeaders) + return this + } + + tableConfig: TableUserConfig + tabRows: any[] + + /** + * initialize our formatted table. + * each header define the width of the column, so make sure to pad with spaces + * (we stream the table, so can't learn the content length) + */ + initTable (tableHeaders: string[]): void { + debug('inittable') + + // multiline header - check the length of the longest line. + // function columnWidth (header: string): number { + // return Math.max(...header.split('\n').map(s => s.length)) + // } + + this.tableConfig = { + columnDefault: { alignment: 'right' }, + columns: [{ alignment: 'left' }] + // columns: tableHeaders.map((header, index) => ({ + // alignment: index == 0 ? 'left' : 'right', + // width: columnWidth(header) + // })), + // columnCount: tableHeaders.length + } + this.tabRows = [tableHeaders] + } + + doneTable (): void { + fs.rmSync(gasCheckerLogFile, { force: true }) + const write = (s: string): void => { + console.log(s) + fs.appendFileSync(gasCheckerLogFile, s + '\n') + } + + write('== gas estimate of direct calling the account\'s "execute" method') + write(' the destination is "account.entryPoint()", which is known to be "hot" address used by this account') + write(' it little higher than EOA call: its an exec from entrypoint (or account owner) into account contract, verifying msg.sender and exec to target)') + + write(table(Object.values(gasEstimatePerExec).map((row) => [ + `gas estimate "${row.title}"`, row.accountEst + ]), this.tableConfig)) + + const tableOutput = table(this.tabRows, this.tableConfig) + write(tableOutput) + // process.exit(0) + } + + addRow (res: GasTestResult): void { + const gasUsed = res.gasDiff != null ? '' : res.gasUsed // hide "total gasUsed" if there is a diff + const perOp = res.gasDiff != null ? res.gasDiff - res.accountEst : '' + + this.tabRows.push([ + res.title, + res.count, + gasUsed, + res.gasDiff ?? '', + // res.accountEst, + perOp]) + } +} + +after(() => { + GasCheckCollector.inst.doneTable() +}) diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/hardhat.config.ts b/dependencies/eth-infinitism-account-abstraction-0.8.0/hardhat.config.ts new file mode 100644 index 00000000..cc696493 --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/hardhat.config.ts @@ -0,0 +1,78 @@ +import '@nomiclabs/hardhat-waffle' +import '@typechain/hardhat' +import { HardhatUserConfig, task } from 'hardhat/config' +import 'hardhat-deploy' + +import 'solidity-coverage' + +import * as fs from 'fs' + +const SALT = '0x0a59dbff790c23c976a548690c27297883cc66b4c67024f9117b0238995e35e9' +process.env.SALT = process.env.SALT ?? SALT + +task('deploy', 'Deploy contracts') + .addFlag('simpleAccountFactory', 'deploy sample factory (by default, enabled only on localhost)') + +const mnemonicFileName = process.env.MNEMONIC_FILE! +let mnemonic = 'test '.repeat(11) + 'junk' +if (fs.existsSync(mnemonicFileName)) { mnemonic = fs.readFileSync(mnemonicFileName, 'ascii') } + +function getNetwork1 (url: string): { url: string, accounts: { mnemonic: string } } { + return { + url, + accounts: { mnemonic } + } +} + +function getNetwork (name: string): { url: string, accounts: { mnemonic: string } } { + return getNetwork1(`https://${name}.infura.io/v3/${process.env.INFURA_ID}`) + // return getNetwork1(`wss://${name}.infura.io/ws/v3/${process.env.INFURA_ID}`) +} + +const optimizedCompilerSettings = { + version: '0.8.28', + settings: { + evmVersion: 'cancun', + optimizer: { enabled: true, runs: 1000000 }, + viaIR: true + } +} + +// You need to export an object to set up your config +// Go to https://hardhat.org/config/ to learn more + +const config: HardhatUserConfig = { + solidity: { + compilers: [{ + version: '0.8.28', + settings: { + evmVersion: 'cancun', + viaIR: true, + optimizer: { enabled: true, runs: 1000000 } + } + }], + overrides: { + 'contracts/core/EntryPoint.sol': optimizedCompilerSettings, + 'contracts/core/EntryPointSimulations.sol': optimizedCompilerSettings, + 'contracts/accounts/SimpleAccount.sol': optimizedCompilerSettings + } + }, + networks: { + dev: { url: 'http://localhost:8545' }, + // github action starts localgeth service, for gas calculations + localgeth: { url: 'http://localgeth:8545' }, + sepolia: getNetwork('sepolia'), + proxy: getNetwork1('http://localhost:8545') + }, + mocha: { + timeout: 10000 + } +} + +// coverage chokes on the "compilers" settings +if (process.env.COVERAGE != null) { + // @ts-ignore + config.solidity = config.solidity.compilers[0] +} + +export default config diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/reports/gas-checker.txt b/dependencies/eth-infinitism-account-abstraction-0.8.0/reports/gas-checker.txt new file mode 100644 index 00000000..0f00a175 --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/reports/gas-checker.txt @@ -0,0 +1,47 @@ +== gas estimate of direct calling the account's "execute" method + the destination is "account.entryPoint()", which is known to be "hot" address used by this account + it little higher than EOA call: its an exec from entrypoint (or account owner) into account contract, verifying msg.sender and exec to target) +╔══════════════════════════╤════════╗ +║ gas estimate "simple" │ 28999 ║ +╟──────────────────────────┼────────╢ +║ gas estimate "big tx 5k" │ 114440 ║ +╚══════════════════════════╧════════╝ + +╔════════════════════════════════╤═══════╤═══════════════╤════════════════╤═════════════════════╗ +║ handleOps description │ count │ total gasUsed │ per UserOp gas │ per UserOp overhead ║ +║ │ │ │ (delta for │ (compared to ║ +║ │ │ │ one UserOp) │ account.exec()) ║ +╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ +║ simple │ 1 │ 77452 │ │ ║ +╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ +║ simple - diff from previous │ 2 │ │ 41508 │ 12509 ║ +╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ +║ simple │ 10 │ 451096 │ │ ║ +╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ +║ simple - diff from previous │ 11 │ │ 41565 │ 12566 ║ +╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ +║ simple paymaster │ 1 │ 83158 │ │ ║ +╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ +║ simple paymaster with diff │ 2 │ │ 39902 │ 10903 ║ +╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ +║ simple paymaster │ 10 │ 442507 │ │ ║ +╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ +║ simple paymaster with diff │ 11 │ │ 39915 │ 10916 ║ +╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ +║ big tx 5k │ 1 │ 167230 │ │ ║ +╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ +║ big tx - diff from previous │ 2 │ │ 130735 │ 16295 ║ +╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ +║ big tx 5k │ 10 │ 1343952 │ │ ║ +╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ +║ big tx - diff from previous │ 11 │ │ 130732 │ 16292 ║ +╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ +║ paymaster+postOp │ 1 │ 84501 │ │ ║ +╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ +║ paymaster+postOp with diff │ 2 │ │ 41294 │ 12295 ║ +╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ +║ paymaster+postOp │ 10 │ 456054 │ │ ║ +╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ +║ paymaster+postOp with diff │ 11 │ │ 41236 │ 12237 ║ +╚════════════════════════════════╧═══════╧═══════════════╧════════════════╧═════════════════════╝ + diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/scripts/check-gas-reports b/dependencies/eth-infinitism-account-abstraction-0.8.0/scripts/check-gas-reports new file mode 100644 index 00000000..d0af47d1 --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/scripts/check-gas-reports @@ -0,0 +1,17 @@ +#!/bin/bash +# make sure gas reports are checked in with this commit +# dump report diff +# exit with "1" if there is a diff, zero if no diff + +folder=${1:-reports} +git diff --color=always $folder +git diff ${folder} | grep -q . + +if [ "$?" == 1 ]; then + #diff with no error - ok + exit +else + echo ERROR: found above unchecked reports. + exit 1 +fi + diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/scripts/docker-gascalc b/dependencies/eth-infinitism-account-abstraction-0.8.0/scripts/docker-gascalc new file mode 100644 index 00000000..adfe4b24 --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/scripts/docker-gascalc @@ -0,0 +1,7 @@ +# run "yarn gas-calc" using geth with docker. +# (if you have geth running on localhost:8545, its faster with "HARDHAT_NETWORK=dev yarn gas-calc") +docker compose -f `dirname $0`/docker-gascalc.yml up --abort-on-container-exit +exit=$? +docker compose -f `dirname $0`/docker-gascalc.yml down +exit $exit + diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/scripts/docker-gascalc.yml b/dependencies/eth-infinitism-account-abstraction-0.8.0/scripts/docker-gascalc.yml new file mode 100644 index 00000000..ac6b0550 --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/scripts/docker-gascalc.yml @@ -0,0 +1,23 @@ +services: + test: + image: node:18 + container_name: gascalc + depends_on: + - localgeth + volumes: + - ..:/app + working_dir: /app + restart: "no" + environment: + - HARDHAT_NETWORK=localgeth + command: "yarn mocha-gascalc" + + localgeth: + ports: [ '8545:8545' ] + image: ethereum/client-go:release-1.14 + # image: dtr22/geth7702 + command: | + --verbosity 1 + --http -http.addr 0.0.0.0 --http.api 'eth,net,web3,debug' --http.port 8545 + --http.vhosts '*,localhost,host.docker.internal' + --dev --rpc.allow-unprotected-txs diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/scripts/gascalc b/dependencies/eth-infinitism-account-abstraction-0.8.0/scripts/gascalc new file mode 100644 index 00000000..b82f5327 --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/scripts/gascalc @@ -0,0 +1,15 @@ +#!/bin/bash + +# run gascalc, assuming "geth" is running on localhost, port 8545 +cd `dirname $0`/.. +function getClientVersion() { + curl -m 1 -s -d '{"method":"web3_clientVersion","params":[],"id":1234,"jsonrpc":"2.0"}' -H content-type:application/json localhost:8545 +} + +if [[ `getClientVersion` =~ "Geth" ]]; then + echo Using GETH on localhost:8545 + HARDHAT_NETWORK=dev yarn mocha-gascalc +else + echo No GETH running on localhost:8545. Using docker.. + ./scripts/docker-gascalc +fi diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/scripts/geth.sh b/dependencies/eth-infinitism-account-abstraction-0.8.0/scripts/geth.sh new file mode 100644 index 00000000..b82a0d2a --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/scripts/geth.sh @@ -0,0 +1,7 @@ +#!/bin/sh +name=geth-$$ +trap "echo killing docker; docker kill $name 2> /dev/null" EXIT +port=$1 +shift +params="--http --http.api eth,net,web3,debug --rpc.allow-unprotected-txs --allow-insecure-unlock --dev --http.addr 0.0.0.0" +docker run --name $name --rm -p $port:8545 ethpandaops/geth:master $params diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/scripts/hh-wrapper b/dependencies/eth-infinitism-account-abstraction-0.8.0/scripts/hh-wrapper new file mode 100644 index 00000000..ada7d62d --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/scripts/hh-wrapper @@ -0,0 +1,5 @@ +#!/bin/bash + +set -euo pipefail +export FORCE_COLOR=1 +hardhat "$@" 2>&1 | `dirname $0`/solcErrors diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/scripts/postpack-contracts-package.sh b/dependencies/eth-infinitism-account-abstraction-0.8.0/scripts/postpack-contracts-package.sh new file mode 100644 index 00000000..6e1b2398 --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/scripts/postpack-contracts-package.sh @@ -0,0 +1,6 @@ +#!/bin/bash -xe +#echo postpack for "contracts" package +cd `dirname $0`/.. +pwd +rm -rf contracts/artifacts + diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/scripts/prepack-contracts-package.sh b/dependencies/eth-infinitism-account-abstraction-0.8.0/scripts/prepack-contracts-package.sh new file mode 100644 index 00000000..b0c90e0c --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/scripts/prepack-contracts-package.sh @@ -0,0 +1,17 @@ +#!/bin/bash -xe +#echo prepack for "contracts" package + +cd `dirname $0`/.. +pwd +if git status contracts | grep -v 'nothing to commit'|tee /dev/stderr |grep -q Untracked; then + exit 1 +fi + +yarn clean +yarn compile +cd contracts + +rm -rf artifacts + +mkdir -p artifacts +cp `find ../artifacts/contracts -type f | grep -v -E 'test|Test|dbg|bls|IOracle|v06'` artifacts/ diff --git a/dependencies/eth-infinitism-account-abstraction-0.8.0/scripts/sample-script.js b/dependencies/eth-infinitism-account-abstraction-0.8.0/scripts/sample-script.js new file mode 100644 index 00000000..a2885d53 --- /dev/null +++ b/dependencies/eth-infinitism-account-abstraction-0.8.0/scripts/sample-script.js @@ -0,0 +1,32 @@ +// We require the Hardhat Runtime Environment explicitly here. This is optional +// but useful for running the script in a standalone fashion through `node

rU{(n>dhqcW(qHDUK(OH>-YW4zrV zMjqX7ZXi>$%4aIYNv(QS+-m18J3mUe*3R91_0Hs_bba z)gytG_mo3wL=O?31XRMIUnACI?UOz9f1q6)P$_{LJjp)(FkmcXM>uC=h-p>l^F0=y zhWCxmA4uUmyx{EacQI;RuGTu6z#}V(>gd8N^R%tmoo!2VJszvl*hf=13s%>xOtbdb zIG~T+84V>5>~DJx8e=u#2G+PV={AwP0W;ZK zUn_`gYv*vqKF|Ce;dZX6((ML~&ns{aBi--c+SuyL9{=PCaKKN#fLH(qmeIZLkgbLG zK7=|tyOs(_ZrbNXQG!GxLn>p|s zE$=A2K|cC$_SM`7@X1)GeC!&`&dS>&9r)1!IRY8fT9ZAb(LRJ2@|1*6qeF^%S@hVA zjq{$(c~?5rxbGT)XE3KbUJ2dNwfTa$t~6((G`f`ASD@`_gRO#|HQK^kpT*4a;C)5| z%)8Co3P0x#f>p%ZnS!I%of|m`e&Oq4vo_<1h!fLOHJVrxBtFW7M}jkiGtR zi*<(!Q*y&2TpJVBl$>5x4{+aT7~s>{VzdGzB%IZumS=Y|KH?+8l%vq$ke!}s=r_~Z zgwraME1NG_UtSe9bbNc!$dP*JYWE-ZRnzqaIdHu5!ef@(8*oE)w$GeO53M^fo~vLkMuM z@Wsz@)#R^F-13#dS1UGK6sHwn?b~!t4v)cY7YCFV{-Vj!j=AQyY9)D3rXN zg`AYO|Kxs2azhvkFPzOog$NeKYb1KIlZb6}4`|g>p6y7;NrtMrQBx{%Tr$j+@V=YO zam5o)(Q+EAG8=f`ra+OPOxj z?wJJ4hp}Em@@Bm^I59KpG0m1YIz;lidMOMBNmf3fBt8qdbdkwQXRgY^y*v{v1fevG zHookC`JF+)M@V90LJ|i2%gZN|y^kMw z!2=(q(gj05eLyJrfmJMAXh0F$Q`@4HcUa`b*3nfjNV=;n@=I4{KZf~Hnnd%t-?*1H zVYQi>@!?gXi-L;+Tia##E8(oFAIa@c{HtONYBR0}+%uqMN22=-uSRA%hTW^|u8d_I zYt}8ZXPV6I@9D+Lj_E=AisX)QP@WF>GbU40A{|b!{1=;)Al9+GIM{7Ag=K;6o7eb~ z(2AIhNR^Uh1yGe@I(?Wk)D-%c-U&~-wW7pQ_Z|r@NEU8T3?5s$bwR((yc-V^k@`?#v^wzV z_4}j6+!cz!%l=r5^x7Am@OHTRZKvLMDT`Ur4_e11Q+x10h(00$?0(~}DPjQJIA5^F zD?FZ?!HPoK6i9%1mDMWzB2%sL9{G;jJ=C&mM2&Cx?mW1qFLklxj@8IN?T-FSS4@RzcMo{Ly$S@lSA8szx+(7KaH)w=U0Fb5{t+Tb>So>~ zqUo3d`NSpr)zGiaypr+Rbj2>*k)w`s((6~Yc|?Z^NFj~p&Yy~hbXh=B?@FI(thg?l z!iPXa#%?{D)<@E~+5W-`&4`V5S#ygk2MuvP^QF2T;!5IkZfRkql{&mf!&P`vBSbPc zFI{6xbHS1_Yz)OT>fv;X2Ywd zc_oxL1nZyb)_mfra*3wIfL(eLv9r*R0{cqb8%`nnPAyx_S&i(dscqlCOIdLfJDC+_ zbHq-^s8q+|t2ef!+$e9+VRpr`Xe zPv?W3&IdHXpL`y6Iv?zGK0qVycpNy6{a<4#ojm%lor}VNYj;4A4A7)HOW=S3SItb{ zM*q(rBmdETeP7EIXzRE9OaC?K{F(c&-<=-YNP$nm`hJKEg&u2q{b$XkewFR=FQgAZ z^ylatCrjwp;tG&O{+qahFat;LzX?<)nrDBN8iAY>yFW=UzlPBnG|pV%02+vY1lj-j zwfDCeo!2lrNxi>_(RVb?Vgy_*|1L}JZ!uyz7e^v-U zHz55ROvUeToCOIG9Xx&g{c}J%EDU@AuBy;B#D#lWOl5LHZ8I8IS{_#AlyuwngGoQ|E}P7@Fa`X@J-0rLA4Netp6q$DHUG7x2xbPvAnE&(T!QUZfV*ZU63qD_N{w$aA zJ5lcpC})BT4E=MB{==X;IpF!lsQM1dS*RF)@5J?IR5ARO{&{i+_KQ%_10w0C3-J3U z22fD{V_E)IQT5kz1JL>IyOVRmU&HDQDrbr-5bXC%R_CxfUpt(frT!vT$BFA)Vg~{0 z{HG^*zg1lQ^>p+63Os)T|KII*ID^TVWX1gFvizNa0-rku1{?>zm!toR8w+IsG5nw} z*?p`p*|$9^96sFCA5SZ%eb z+~43Xy%TseUQ-%UJ%s8$idF?Lg`xM{`Tf_H!KK~ zdl;RTWxBP-!wsbU?t}z-gXWQeh28dOjkpKlOdOy(xd&$=VyTiQYRlJN`UPU=FRA4p zrMc;%(vAt8bJ5)L?cBH)x3!p1Kz#6|Bg8&Dv$%zYwKv*siX%UIy@^*_UXK<7#KLPL z_{_|5?nCmWxVP-HAJgL3*0lh6%y{jzuVZeXXzx1R9l~I-3t=38=w3bfa`#RN39epV z1_`(UaeM^z<=(}i4mhs`zgQby^cz}-x7bl^Z*g7|6Vr$z=6Pz6buo)-fC43NO>S2^ za*|oFOxPDoUV46)gW%A5d+8Gl-0wnR92wEAy=$PJt-y_Jx6bPW(m8rOQ$lmZzQ1Ps zH9M5A#hPgE#S6xS#@g~k0!O_S9;ekBSwHw^SG700#Ydg@HkVA~*xacHZyL}BFV65i z{Mw-zFv+kp`HWNSNw#!G8gl43WLUf19-8xFlTpK>^Q}t@bG~6+BbGnmLz8zm#Jj9ACfPmPTo6I=~Ucd z-Sh**Gp!C(ybBi(P;DT=#xtYjJ}JH7Pv3T_aT@ETk#ad(l{6xuCftuxzlV%X3b!34 z`Z%d9l(IoBZ=+jk=mv#(Ml^fMCkguHVg0RmeqPlc=_2fuYo>m<@E$~(5@C&U&J#NMj;#|<`dGtBNw=%ArsGE#ix&i?~f*dr8_Mi&;NS*-U=_V9KV}Tl}~{*w&n9`?@L`#UxymiQwN&oO2R>@J|&g3Dk>dEZlEtc*En)G=SlYXb1t zW>}`4B3zO&dR8ytS0nFb$|c^4NwIQN#TWQoTL0{hu6`Vc0Dh2m!EFIWmq%9wIukK{ zA>lH@HWDHw+bI*&0};;N6qmwUx}{%Ru1R^LIa#3~Y)4Ie6|=3A@=nWMO;O;^G|Qc< zuJjmKeU!UK+%TwOGLlnfaRFm`Ci+#USQz()Odge3(#N?f3}mUbn02h{I6$!Cw26?A zO|+4|q`#5yAu)uUuli;HoXyMkG+Ss)H_Y@6F|eXux`A#i?88%zGmhOALqzw(AP0h) zY=W_wc!E*b*DM^8pSjdL!RXw3RS=~=yycLgR!>hm3pYtLvsoa&eWfItZF=e!t)b-0 z?HB4yFL>5U=6kLRq58t=Os5}w2!bG0E#cSLG`#{1<*{s<`Ip!A8yHNq9>$Dt;Av>w z(>3#u-6kbGn zcb%9}&;F7`xP1_%2K5BE9_;fe@OUMXsZ)Qj@P86QK#`N!v*BpwRY&kb^O&?Pubxhy zn+vk`vat#)uWh_eqm;%nkYhh~%RZXK=3NR-S~U4XyW1CSCQEoqY|FdnWf-#`$-(Wn zWt%6Jsh3+R(27sVH~A_CX4W-q$z|4Mew=}<;jk3a7TQOcgfFrUL-)n9#BAUyx0aUz z3ek?3S|zLomXmvI6b3BS7j`i*j?`cJr^+8Ws^E+cj!B5Nd35Y|w~Wouy+adDZop)P8bhZz#g zWUPXo4^B}F36Ut>jiTF9W^V~ZUq{pG^sW)HNG_9t!aFUgjgV#ad8e(#n!_c;XYG8( zj81x~#TL2xp=~J#)WB46sMx}y>Pd7>Dul4?WG>+kDl4Ev9Z%9!L++R?e#D7_4paoD7902^X`#9-z;>K zbH|QKclM;jfKIbfzDM>S!4nQg+Q0uKmZeF6W?=7i;}TQ2=2KidUjO2$JrVUZ66hMoW#_la8S;|W=-+fl+1e1FCHvzTsb}^U2 z6}q=7%x}&v+wkJ^c**otDnO_#sYP~%F-(qDH^qget)0we<){>HC)U0lp3J05mL`dg z^Rd>>_QLK(lWCN9ET2ay9hxk`jZ4BSr6bmR5Pp{cO-=089A3x8a_=wi>qTS^4<`tZ zwijJQvhQ;w*bO|Prf^kp16@0meEe~DM^vRU{*5Y>t~@zIcz{h6^fsm$F^Ic%QzdNQ zOqz5f9){y=0;9X#IhC+p%3Vf3!+MPO4pd@a#r?}|dUy|4Qxd7VsAz@<$ zcZ1(K0ZM+5rE2fspi%IQgCSJsnM&ZpukMY(rUn%8(b0K%Qf3dueCA(2GHe%WP7x{B zRtf5SZAlB#C3|HgpPm^mp6`_PI4e}~4zl$nD6XteA5Qot6UrryJ5C|RH#W?Pb{G>(R-q%@vsQCpz~IF}tS1~Ukl(knaD{cjLa~XBL7Wwa zNVzaL*D_$PgOY#}>q#BLDwjtR!YRE&^4jLP-Lmm=zleLTnHqi1^vpHRYXlx&a%5v2 znUT_Y`6%S(NpO)(c=|Wl2(J2Se;k611$(I*`eMZ;T~Ci~A&e8agE2w&9xbd$Qa&%~ za_^WqA1j}W^`X$HS1udb3!7QLy9WBoqpTsEequ+9^S!Ug-QJb7cDFmt@TcqEBrCrA z=<}s{7eh|pjo5ddKBI9e_e&!i?P(u%XOMk1ex5F(CtfU65+TP3X6BDhC=D9#)6K}? z8=?{?R{mscif{o4oMF+i;cdUWtSGAHs&`E_60uma9OjQjOS@wQ3Tg-AghPM(>!JqP>z z`YJ`-rVuKqTIMq=Ug7xj*DoX=(TYZZ(7HaP%-XcCS6>j%y<64Xrb6J_-iTb=jI)DJ z6^@LDts7g|s(r1!!cuOJpA9_$D{=FIUsI`m`3J%{uo0NHlXN1~Gc=Zq)fsG*!v_3W zzbk2TTvn{+U1kr@xpY2|Ksk<1EK!D z{s}EaDy8h&(1I~$vu5AdB5O4mjD6q9QYl#?m9nI=givKcy^|Xj{+M2SSXHbw}?`SIHw;giWgH9d2=himJMj<8?f^6}S-EzDsZG@grIGa;D z^3^&0JJLxV`}?KOTONO`qWfwW2(&EJk1&8Z>#fRTnO;g3fvxJ&k#pPKw*&jX6vdVz zZJ)Rr@-(bFH`NdhA5LTFJs0fQS0 z8XI?pj#nhC8}FZDtS|A)~2*I!VT4`2oF)vgLtK9?q60oJDq6WMP~S z?g}a3DM<)AUp}^0W8o(*iwQC@NRqFDjPlF)F~#Ib zN=|-w#!&O>QbIRA{yDbqlRW3%Vfk&|*H}>5mC*d=&in~S{lx^2^4a}*g5jaB_n*0Q zd+I~wf@W`!vF{C#;YJB}c} z>BpbEek%*UU?xIoFhx~7(V(Sd7R2dnNwv7^s{0lD8;IT2%1;@nnCv=hk#&1N9#G;F zaBgdURLa*7-MH7?@*O0hEzR>Bm=(Q~fh_rh4Sm@5F^4eztD&zksGYPf*VSx>8{R)S z*@#jU--p>;C3o|ry!a>CCNC*wu8C*NsSrn*qWybUuXA$%xy<) zIJINQ>BOnZuQzIgzJI%Jde1I=%9@e$|yPPze}iY&f9-7SyO z`}r%a9_6k(6I}bXrr`OlU}IUMpbG+L1kL~pa3<@Md^r9If8;tdn;l1aGrC`UUa(1{ zu+(yN+F=`avh>}iYuNHVyUIQ)#K&gj5AVBdhmhOnA9}!Y)aEJUCYkb1&MA?QyP4() zq@RBgXXq5ra&b))If=!_9-!q24dnKq|-AP z-74GtRe_DSr7GHH)S><&`~#Jj$mV{MIGzM>qZa-Gt4+ zsjuE@j@z}-)}K5Pm|f)O zJxA{4@;&wYhRt=%T;A`sA5DuvGA$Fcqwjmo1&9?HK4TOgS@3E35H3*$RVt#RDm$pO zKxbOQt5o#)(W&c+hFu#n>t1Cf-h^E{kmnOk$18nvd(-_}N%aAF@Hy!wokeFze==$c zt9O6KEne28neXeQE2ic2t*G(X>orlJ_+nOls$RR5)j-!u$4n!SS6z3^O|1B9Mo{o6 zM``4>)&b~tOJmWg*$q8yBAp}YXR^hVvtXJ{jn|y7I+%68&;G(6vhZamhL46~>`lX` z`OE;%FZuR7gNu`6Qha!*nq*}GTRafeRgI~TxuE?u&htuQ;0uO4Jm zIa(?sTbkH9*Ck(Q)shBHRMg8kDvqB84Uy)`Fw~x}f)` z3+%LaP<*@1kR}k;dEudVGbF!Poa2R)>W1iwen)|U==R>XPdv4x+!v3I%fcp6J)0nI zB9RJ_hB-&V-rwwvFmWNbxT?GVLe~q-Xg-|$nB92;FF#H8RAF2N#$$IC}E%JziYR17H3(m#$JY)$e!bSEKQ?2GUAQ}ve$je}}c z0-jc`JDi#|Nl^iJ%naX=`(j;xRo=rxVaX$7#&5K>G_0bAHkOFW3Sa+9JtZmI(y>2v z$1I)On5wprjZG)92!jtj{pf7U0?JoLA#awfU`k_Bx?hHlY@M1Yeu3Exq0c6jr8 zHhG1T53`ScBrZr04*Xb^CMd#}3NGU?W>^><-E5ZYbN-cy*54eshA@Xs#QL zT}taN_&C2@*So&#$;ji!>B>On*nfG0-Btwb+By}p9yvQB zh4j9{t{%55eYNs!`3)jxS@)$W71~o->z;bM-h$jB6e)L{H@F*XEUgqthdJb8KN#>h z-RMei>Y+n!s#`V+pATp=+&cc?(sPxvM_kGVT|___L_CU{h$ED^`Ge;yoqTM$h)>(r=+z{VO#u@ph_zEz^j>8 zHqdZgUV8eyVnL>-eXXiwrgnBT24C{I_C=x3Jj0shu}|G-7u#t=+&Em)wnp zvazp!%9C*i*4(FGFf>>_ckbzq)E$F92npr~ozsgMH2HNjT<+xK-)LK6WYf>F2}s!< zj~puE5y*fs+OkoS9sg)TZ$Et7dHTj)(GTV3qkBKQ3+9E2ZZ&QQRum)KkWpwBX{W+| z#oJwnVe98gM*fT2{Yvff&o!LKUVS2{EYfpp>oAS~g*Q}1M_3s7YU?+{?cypT*-dXu zrELwqv6m~u(tN<)zq)9Hf%UE^S7!!LdBSM9>k-S;N&RkmMmuK;zIPwi-xiU$K(9+1 zdD%*-$|bR+pZO*e<(GbrK{kfi0{^B3Ko8!&OR$m93|{2RkkMfD|NT6Zvsl#lM}Dg>qNIX zZZc9p@Xn2%aR1^ivcJ^BY2onTy&_PP;m}KA+h>u%cSSPfRnxYB1ktuS*m4|omsC(N<=)n^{4M& z_593iP&;%dFi*X=wQ=vs-YlQOC{6BALH zJ<5ElNhPPkvE(*P%;lk&$pu?GLt6*YJf(M1Vs2h)Mb-0eC1Si)ZF1E)>MNlKwzvh*9DHA;JOi=v2+n^`c?Nzn z<*&;#KrdcGc?7Y10`yeGzeWPQ2_&(60(9vl{GC{i0Xk+AUK7hPki_wj#PLAe zU;N)u#PI<4B;hr2JkaQp@R~RtiZ~vMI39{P9*Q^~Xse8SKb)U19-N;r9-N;r9V^bye5tZA&v(jj0ZN|{>REj z@Q>v0?WzKj)unxTlD$F%U?2K7o?KhDt17sHDHnlzh<_6)u+zM9{~3+~bVP(*>3`L> z>MEA>Q z6aX%r#`<|O8OD!T(zyTgR%=PORz>U=Don_V!;$#d5{7tBSfUJn6+x5orD^$p-g1!~(jO5^Y8 z6$vaPdIbf6#lOW`tr@JfM)E%!dO#tNCCelL1B~J*lmK9t7C=G&@kwasY-PnKu#y%W zzXo1|CXh7rAh|h`h93VLH%Dw{VI*jb0YYIQ0>(fW1q20*K}Qc`z?f_zh!GHg3!3ty z5GcT~y!;3{e*OP9F#zEW9Ew7MrTQ-zz?ZK6W2WQ3iUBUSum%i3rxae$E=3Ru;}U!Qa4Du!w~cuKr^fI5}W2d~g#C8g7C_zywU;f+&cfi3tj3f`Woq z2&fU7-xOtPio^iP`HXFCoE!iZyd&QVg}^0P)&d4#3Wh*X{GgUWfL~zgwjoGdn*}%u z#MBU^ATQz{2IKGYJrG&De@_~`a{l1*P=60D2&kb#2*L!w{P_hg#M0G&On3f4xYii| z;#3L-niPSwBZ+oF5nuueBB2l*a({|;t(b_ojOH3Niv%hX&H4qZKSi@vK(*%h_lM0Q z(H{XQC~|=cB2hSQ9|SMtUt+U<<*1QGTUi;QjV%e$?}{Q>eA<2uN`>oBLA34=kQIUu z%oQn8po)rk_5ZxNS{qVpjC=(Ik-R7n1MtI1Z4&A9`y+H}#ni*?)2uZM`98GFDb?4eNhOzhkq9? zC@*M{iI1vC;DUiTf^hZUVy4yt*IHwCqyR4*B?uAVC-rnt&~%3%utW&_QQEa)CayJL zC&lWAYLQ~~=cv{StkxKiS z-?UqR$!<@%{%q~XJ#q+u)O;~G=fzo7L) zy?#OK4^pocXst1VC$(NbwFo3ndEpSS;(>C2oZnJ@>ra@B%Xi!eXRiLH^#ZN=phW9M z3K(MP>K_Rh{&3nF00U`xun&R&sVh=X2n8&!P!v=U^rHWxG;H~Ngsd^mPKwq~_4);^ zKS;e+ptaVRo+MNA(@v2jmcbFae@hyEY4>||j_Tz}EjVPYAw4Nn{7cz(Qm9Z%7yr+j zt+hh6#)zIYsr*x`a68^$^@sula({?ct(blPh2%S+@+NNUkmB@bsMHFaNaOdvqy-W{ z3jRV1R1au@SgOMbv_J;63uI@>-=0&hC`!9}m?;l4QK7sATfU3;^mN7Iw~%{)7bq(u zWeQ8HkXkvFnFS3EJ`|SP>Ke4TDBJWsqDe{-wcgcr(P@5If%fI0d1&5*TEX_fgd% z&Ud%mW)}xWZC`U^E(KltO516% zSmjp%plX-$9kkq~k#oaca(K54zHKHMzHMfAtQwi6b>Kc$im45mRiBTlj`Qz3)>y?H zZ^l6N&g@D3olF*F6IMa3pNE8K6aO@IK^`*>a~2F`!wA2J$UG{q4xR7 z{U;oseagIOMJF#kf6Vk5%0p^iJs|(<@YE^xD!L9MqdbZbPvvk*i0QkVLZ7<(2S(-Q z)7GbXDW2!<=(|Jx=>R6#xijx*v#qV4xYz7d=Jd6l=Fh&wM&EDPKd(G(7AJ%B<;@ckz5ew!!0DDP4Ur`SVlXRmDR-oSN{94PpCmR7<2m zw7&R7s-O;YWK(RL`;`q>jb3DY6td+B<+iS2q5RysxmNi!RFtxOoNTH%qau0>8R{Kl zU;0NO`oxbyX;0`wE~bv3JMUtb8Xsa5=-);jdNR;%JL|~B2<;iK=i`?zoE6%Bfeof% zJLDYev&B6&13NFExHVbWm=%hgdS>fs`pwPHOdqQ|C9LC<7+9Y_kEAL)r{=QW^BGq@^xpg9-zj5_ zrvt?Dp2YrDj` zO;inX3}5N(KUL6O=cZ)fG)f;^IDL>x=!4+^ONUa>`^kek4E^!!FC4Hlb&%^8HMj4w zd%SxY>m@v&UM8U`gMEDF@4Ot@U zw4EnI>O^#7)Ddp^(i9~}TrRn(Yv#EW?2b8+{x9Sd->`3(q^>bGY z%4Oojl7l`O?zFwB*ETzd(kfLV=YMLRvv8Ql*))hbqg&H-*kvLvQz=%gY2@;RyXiy! z*Crn}xwt={scKG1Qg14Zz9<;7(H?%50g=OWJmFz%Ve~Lo4%Z@4RHZqR*Bn|vhi7O= zuZVuXSH_;$E`11|dCE1MN0bbEZ}w2zhS?wmi;{LX*2Nu&HBFIT`Z zkBdW`&w|4Gq)#epJxvizu@shsRGOAQz7_91#!##l>u)TuEr@l@E|rESx27psHM~@* zRRvIKm5Mk^hTU=%63VXRGZDJU-JDBhD0ub!YY!oh=UiJ<rmIiZ6$R4 z(QDR6yTh@`I*q0mS*dZw=IB5~=Fy;jiD&HdoV5Wy7p_Q^+xu^b3%gg5lF>I3$jYm+ zkz4X9U_%*f(s(Cz6Sn{A@tj*2A&ydh~wBtsD ziZ?Xh32To0R5zI6&b=q1VDa|7{)cDN4Ga*k$3Ll*r{0W9P&UmCoqPe>r!}|f~Z^M|3pjc`!Q^C!j=ui4%{hDRi#o#I+9B*?#+Chj#J|HF{rJI;!E6lW@=tY zX_s+ts*fy_iw8_7udnc(toH+RYUMgn)u9}?!|{i;K2%#Yt4$74JpHb{&P74Ke^T>8 zYOqja2DK(-n@=>Vwn`yQ8UD<4=KA;fsUF)i2JZ{*?Cj;RpE{XlTQvb+tc(2A6zuPE z{2`Z2jgM-7*R;=K{+aLS{V4?(pCc^_b>evTenD=kvDUH66B)coF})!+!zcedVut%M zE5=gra`ls-8#?b&f?pfk`^udzdXO?wVp`ugJ2My5$%4XA-0`h?SS6%(j8p0joqZ@w zP$COea)<75+?Fl7_0PHrh_vihkOK@jO;%s-j67>W=V_{`v>iQlvXE0KC@n528EyB} zH)vp<&CJ2L(1;=C`t9v1>fX(Uo@zX;iT<(z_4{vbh<0?bFzDYIV^kDTN($S;pS;^Ue-qArG)a`zCHv@fpb1n>ZVUBbL$qW{waQfU zm7ZcJ)#&T5Dn2JZNWPeEJ6K(>B>enVzHs-OcN2LX54xmSzQG?_@64ZT*9c5%_M%F! zF5t@EbUnL(JN|K-X8*;*^?aWhYaiXAXRLN>?U!s7JQeKn?!dc=sip$;LG0Kz(f(rJ zLGDl)hc~aA9@yCwUD)Kok~m$yi>_BLVx6rY7pE%Ozuu zr_UGjR8bK%)EjB(^f}|;BNB1fn$__}$;An`^bEdcg~_U?ySb_c zr1Nr^GmCBre=w5Rck=FN59D13f9A!qUeH2F)BY`pD)GysBv=sNXJ0-m(x3LN!j_NgwRHm@|u;u zQXQ^Op}hNua>mWQBg_CJCT!I-(yk#B)XPvt(SHc~`BJ*11!Za{&vu!?lSsMG>O1$d z%{dodkiV?yvd{2?&uzGU<3K21f4st_pvxmdZ;7*n8*<}ga=u2yX?!hgr}Z8zQU!iN?rwpYD>ZpNJ`!%9 zfr}F0iv`o?13=)>o3J4WM_0$*y(p zy&F$hxpQzuk{^3vtUiAK?wfp_x)G~SI>#?zYBcJvwWbwa%i_JaFj9IWRbw%9=D~Ne z1#-S4**=%~;_VpmG~9!fnJHx*LkRq11^>vQJz_aK?+657DDo%616&Chw#E^tI1 zFpTp3^unSSdaI($(BBL^tHza2y`lsSN=j8Pb4$nJH@^uuy!Fwe5&i4$VNg^0&oXkORdN>?{&rOwn+ag|)Is+q5G-0d?oVw+plS!-l&KlFHZ z{Hw>gFVHu|Jd%ltQr$Ye5j@;iTWl^4l~YP(tCr?(v^!aR85sWnS77{iRa};oI43Sq zly3AG_YeJX2W|!Nedz@#nLKuS#E}n2p+vS;XTJ8J#ne($8cOqVP^OlA^x#k&D z)zDJYzhlP1OjuOO(^J#4s|0hxGkA-2BF*)=BbknuvaNHWn6qSdGxu*Jcz&j-^Qg zT%#Y)NaoZVq^4V&nP%VoAPn*UP*p0rdYKDx|3Fo7hanTGkS{c zo31j%GTtvbRGNzvVhoEAbk~G(@n#=O+}*y=-WhJei_X*ulzV}8J1mnw;Y~Mm?oFY{ zXn+KLczev~9!J43=OkpWzqQH`s{*Tg^fjk3`m&2WMh$@`-nl#$)apSKVbq-g`>NA( z9^KZpy)*yZv_pYh3RCgrve5T_^^)4dSA+yLdV(V6oRezma^S=9rW%^>^yO-dKlBPJ zvK@avAgZEd;cz4m-Z>aJ+Jc$UBX7R=ec<|bJ$q$Vtwg~_zOYeCE9BPq6fJE@w5J{> zc4-XD9pi%A`QT1DyIqW5|#w4G~;gmtv4GkB%M<-6t}c~T$8 zwxsshzi`^ZCu+;yS!+W5Lig&|Oc!%Y*?uKdj`QX86YQP+b{>`CFG7#G+~`xd-gEoN zV_Prtaeq$FIw^ggM2SHLIhn^>cRenW()X=+cr9`y{bc-&<3=G#`QWYE4q!Tjc|Ez& zMNxVG6}^=N^BG^4z&x^PI%_na!)9upJ)K|1>8$-kzMg!x%2KvIGM(w|?>R<)CT<|k!LN0|mU4zQm*&i3P*X1i z(k47?){(-nZji2a(74|z=180Fgg*3X%1wvy6EY@WZ|;2(t{*0Dt;sb0EZ>c)C&Gob zWXAT|snFDrX2G1GsAqoL#LrBLDG!L1%5Qdu^ip>|111g~FrU%q@1?3#?C;K&U`KCnWBw8oT`*_raeT?meI16uZ z&+cvOjZY7|$~*=;eDtmF8;*(jSMBhfM{}HMW7NuGe1+=~o!ULYTVxITTC0-wuesUedc>m5$J*{uoN(@bY$F1?F$WpNi$@x14QVh#TEm2f zIv2Q}o_q1JX6V6}nCD*(v?5}tQ<-8uq%&*f4m<7L*Ec8aY>nC0>2X44Z_UKI=7X0M z>GMOBrt$>=6VUOIG%7{!dqW$|RZ(sEH~TN7n=|BAS)4O#t)*V4+~kotmGBR#?O@i9k%se(t??Bjjw(r+G6 zQED$bfVS|V<2Y24$41t6Bvqv$aVE{pg7c`&uw6&~QQ5%@+mf2r4Gz}@=C%sTS{HQk zdvHDp;EoVJ^ybkU!6sLWuUB_`@vuH{H%BZ(1vc2pB(1MTNWqujao zp9=P{?AzYgcp&A{iG3=GIWL}@N0uw-S=4?#i(IeSpr+q-u264#`~8Y-))lc0c^aBp zl@huepWXhz?ABrYQd?8TB6Qtp)omZhOzn?hc+B^fyHapnYo?Bi?xAW?mi{!Ey%|kW zGp3ngAff+~@zy>aU%fpqc3-90J6jC7!;(nxJ?d$HZ8BZHqOw40(*3^uq8t;HbSDuq z_bYg*5ibi&Q^)Ph6(WQ#CY=-gU|x1!fB$4*^t*MTk96BMj{_2*J3mQ)Oz|W@2L5nY z15Zo8T?LQhSsnGB2tLG)W>8s^72!#M6&!V1p5^AObBxpwWyk8lfU~3AyAAg6Z>Mp* z9Le#5+}bZ>KU)hRtTbuWGs3Y?Z24 zK2LXz@;Jx*RT_pO3^kvO#0Fz6U&e&PfTHKH1_z&cv7W|eoxX(43JRNw3-yy8yxL^& zc#p4J_-OltzY|Tcsi@w)lK> zt?%aL6Paav(ED1w{^PyeMoCli5FKpkjXQmMO7Djx$d2YJuixs*rk5YL|J7c0e+Tx5 z^>-gSTV34cxie=N*Ol2rc2nCYNXPX+neZ2-Z`U2L-_y8rDi18=(lw*bD^M39pr0hXgW*b_mj}6B% zj@UTiIe?x44j=&{2au6cl_1~%x+ALFe>6vbV1)P6&Idxzt;jdHQnr0gbFW7?nI7r<#l706K){09xc!d1$YRVSc=EjGT`0OfQiHsG-_=g#F4~<5m@gySe5fhXDm^tC5WnF^$-JG0#9N30j2bI%4 zi=W2cDOCEJSHDy)=R6c!K}9WQ>XUDEj`?$V+s%~YeW!xP;S&g#53Vjl!-j^rn6j5e zcTJ|#U0XlnSb#p)Ge&=IW0^|0EM1adRiN$|@P<7wHg0^T=~n6Yx>@ndMHwOo<6^I< zC5AQdc^+iHo4wc+OUO_2xEMQoHFvw)M+{bf-{AVxM0O?f4=6ZUajN;hh4}{#&cFfs z8frdGjH9iygE7XD1GgauF5v5R9Xa$l;1Jxg6~Lqeid*nM!68k;Pa*>jXgy4LjobAE z?-Rg}0Dck~b-?jW!gbs|;Qme=Pk=ZcI68&D4keBUC5{IUxDc)r$Ac2bgA&IB#}f#D zCyoatjweVQPmnmCAaOiF;&_6@@dSzE2@=Nx#i01{z+ni&PvUqm;&?FPcrfC4gr3$M zaD3Bja9_j*)^K72Yp_%MKgIk*cqD5$=RtCkh=lovQffmkyt^qAl>-CeNjN}|70t)-r5FU_PuiuvSE+;SpEFpg% zGH@&zNwi--PeLM~$fc|QD*Lqt$Z&3c4O&KWx{t(G2@1eKSrfpYpW_eHvK6y(ttX6r zo*hN}RIy+1`lD2A1zxzYaSi%KYQ=uqE0RNg2nceCpXAS&k}Im{1XiwM{sS%0k78d0 zjzNiF#YiCoWO>A^e=20S#mE}8On@K43xn}PK}14gub?cwTDD?Vt})R6 z1+O0}MvB*;rDDtR!Y{tppkJg`?5DjVjm7wJ4ZfjpkQMm%OvzRF-&Pnee0t*VA_a)v zR)%2wfO(2=^$$a8jqyEcdhpm0zi1`HV>Y)1SMI<;cztudzm1*RVg^$SdYfTzpP*4Mv58@r~r>NZ8K)H*Su|c81}H zpp1-60JE2gF&twIXd$2iXcHI=!fzzV4~Lk-Fc=6DVPv}E0k1KTCdB~9bhv`?4P=;? zuKr_&^}mY28Y5#t1e6y7Meqa0Ko}hSN+8~V0rEE(3JC+;^MG68AE)EMD>;tL%@k{e zaa{43*BHqH+7%=m4guMFl6wK&tf2xpufPElK>XvC`~Tqv*BW|4LA4;1A3QJ8JA?uf zLlg`S1N3$O8@Kp(S^IvH6D)u3`0bcAm^cAaSO7Z%p@^3h797RlKTMtSKLE=bQ^q82 zO%O~CV&x=>TN4DS(SMpEjOf-@Y`5UI+}7~SNlZG)&5^jZ|Bag?nshh|MegQaO zE&G?~6Ok?O_cUB9>d^5g8rEQjA%JiTXcH3ti~0!Q7}*6OD6j|h2f?*MwbmG(lB(8E zB_cIdFc7@_OH_+=Q*s5h)Gy3<5P=oItugE+v0NnT1Q@~rZ6`?f02}`Y0=FDA{F$P) z%uEtP_7fgbZG!?TpnsXRX=5C)rtVl9vt|9eAS;M~@JFxK0@qLPNTN*wZ~>4PfI>if z7(lE0hrqQ$v(}h=CADKeK_S&F2#CJ^6wO+ZfWsf+`DU=6@z) z!K!5`Y$sW=Y3F@h*G471_^uQ9s*1p~140D*x{f21o`2r#(BtN++) z?Z1ivX(INo_+y}eLitzz7=4wnw|QGjW-~{!$?Lu@lI^5vm-ph|wl~!E%~M%AQBhI2 ze+QWh-P{6?qEX9U8LW#C-2>sM*w(#ThqZT{+QE}6c4&Uipy^D_C{H3wfbc2t7$4CT z9uJxCLu~bx-Nj$;DJ)#}7p>T^J+^J^Yga=uAFqez@U8FO^J6^oeyIQiGv9kom@y_<)s=lLN^VlKHE*oW?<~9hx@Ns`PJ_jqLi1<(*B1G0 zNwZxMK9&=zU4vO?Uf=DpElT>9_th?bIMy-#{i40kZ2hw=*$#ybSG}W-EPM+)<+Cub zknM7e`@2!@eOg8L4{1daSNDGNzGFE*VpBKlKUeo^ioLDOeRP05lG z8^brzQjrg}hMdlq9b+`MzpuQ68b08j)TkpRel=CwVxaipt7c`-t;o*0;o2gqk7>b@ zTIbj-Uq?WZTxYM2&3keT+l7+NcfBnQN_Wy-v=C0xakPdcjOdo?FVKG2*OaZ-b$ZGw zx%2zF+02xLA*I;|(-LOMF*jo<6~aHhNK}eMo?bs-s`1Fx;i~?DU~i-=>c+keQdeIK zLl1{$+)|2mF)Sx5fAUB>`2>aGweeK5lDKJa>FTnOsSspgLs9jt;zLcy$<3u(ZhFg| zL!zcPd*2V$OGBR7PVoqKr=1gR&mot*Ztq#2ce$bgXv?#H#t^3AXPGSq>4$ACJ*RVo zS)ZqgWR&mPdDrM&@!LL8?Kg@JY-e77(N($OZUbNZe#yte>Gb~Vj}$&>y^d$7E{zms z)D1goy@i5Rcx+4weVZ(Qd4>V*_7%G$&+iB1w0;`*RI}e;C$UirwL+#5w zKFJqTn5G}>u5zppOFqFX)P1by+Uq2yQa?;uaUBgLGA!T>z->!PS)*tUG#c>=*6J~AEfRemtn*vP=m_D%Pt7ntWUt$+LG@Oj6$^sUAv&5#qL?DW^||cO6a;ZC)=B%XqVmh3=M!lGx zKgJ=09rhkq@0(r4bgs?lD*0k}pNUnS+c;&_85FAi^C9S~7SR{)sL8u^N3Gp*_b9d+ z4O6Ikv}hgnzj!r`O5qZ%jxuKa+++BqX72M$X}$#yTU=Gk6(ehCRWyv+57|>>#VYyu z7F~Yn$|Btc_WGO92t`c zgzA~4QmC@w#o*el`xTRE6^*yu-RyBCtle-zmM?&TtM+;9jz^|nZ@k+h_+~OU+6_C= z)ITXOnR?TI|C{{*uvpPlSq9GZ}NF(B*cv)g0LwOvP}OCt_$<6|Im+*V6b zpp4ME>JOJJ6-K5ctalqKpb3(ao|w!oxGWL$C^AjE@x+8o-BIhKM}i$?2Ka2TQ@5U`TlatNb*cD#GPCmZqudd=u*x zxGybsZ|GZ=6zPjn1`b!>VNnwUWc`EmN;|@=Sg$ZU*D+y*hPJXYs_Ym#oir+K^-OZR zV#hT(W3!!1hd-ujUQRc5IikW?K7OvzDRMLKW`p%KqVlqrE6Ke@PrxNRjbnrIE=D+G z_TN8GF6W}k(DQ~qPO1N`maFv_ct+$Ec7{rx&I7#Lck|4~W*MfWPq=W>;` zB+N6(X=Iqp4r-bKc@rjsBk;@!6q5;qcIT& z^`vM^11(WL6U?~MUY=PLrS)TrTWv+Woi@yIUF+}9x+;GZ(LchESwD3=cnHNn#TD6h zE^rfBDh7I?;A3O-ewwDcZ2miUhtIxj7k1bqTjQVSK}M%{$t32@Gd3kJcO(P0Ux|tT zViTE{U4Ede4O8fY0)@PVp1xO&n~mN+w%Jl$0SbHRcs--k9XK*uHkKcLesP$o)2+L& zrimg2zImc(SLI#Wr_s>OdU}$TMYL{@{AeADCGJ_#@8M7L+oow$vn!No;z;Y2y>!yi z(9opYA-=bxl_+VIo|`P#?zQ5Wq6 z_6zg-yC0<}zvU{ZA8dR~p!JGME&G*GsW}Iq=IW+JE0Jk;{_DO<$b!x^caz%L%?#QGd)r}xL%q$M2I5r zz7t(0|GVmQuctd`*xRceT9p(1X?rLZV!7rvs112)xQb@I4xi%g@EniLorEs19_gBj z4*cv|ydRwvw+EG1EFOO$PvwC&->D~yi{J9kEPUq6F(|T4zGiEFtr9!%!6BYEbKao! z_25jro&Kr4^CPy7Y{eXPlkX0G8d|VWgz@>bWy;r2B28zn9{hT+sXyaMMq2oFyk?SKLALx3atxQ8hwhSMNiLW=PIAE_xk z*xbj_MgVhLQw}N6HxqmgoVHq$3a4d6seT@zLJ0n7HBBNEKQ$lmYvK4O3Uo*nz8O?tpRmiN|k5!B<=Vg2yizZlWm0wss(& zwS)nLSnIt;L4JJ{%Q0E`V17B_K@`N@(FtSCq2_{daKU0+Nkk%+i?2~6!rlMwG2t?@ zzv{{_Ia-29QdU@?AxAVZcD4>q7!wXztc?lSbRkh02*H97RGH+tAs|bwxJi@-29$>I z+z5dDP-}cSJyEUUaGZqz`n38(MG&R{seb)({(&I4G{y;I?8M=UcChAfbh33on_)Q6 z#(<;15qG-q$Fu&8@VMTuNPHaviSQ&E4<~@Pr1AL4{EM3Xk_{zDq>MpZ0t6+|ju;ME z45`AcE`*>UsKxViSRK_p=91@JAqR{@Ry&2r#KM8QviWma7tYi7=I3?~oP ziPWru^7++lIzMPS3lroAC!|QQf&5S|qJ9&-4mdo8pOAR317CWz1l+IY9~>WAW>@g< zUnZ@BjSJceYr=sxGjqV0p`9=sj#x7rw3D*~hC`otqQH;@$kp!xE(p#nLzdqK$vjOhZI$B}SI8V%BVrvZe=4_nMPFR33US1BgjR`>C+76tgCzTzF7h{E)1pBK3 zzc-Tv6ZX>?FOz+RpFynRXHu3isHpLo~h)XIWkw<4)po8O1;a_2`ez-zBTqN@zSZGb(ncg6xE?+6qYgVWo;z6I#&s{$A(bU^-vLJ-jW;X#+(0>PV+ z_){eA%5QD~OgUR?AgBq@3{z(tW5P6BIlF!%sQ_p+1CFW@h^tnDO@#AzlCJQj$W_)a zS~gf4tP>XaQx6~`7B}sG8U$mo#&bXetFek#g(C5mXSpIH_(6@^@4>}`_1oD7&POft z5cn(0z}2#Gzy)<^tPPNu;3B{ed=RzV;{HZR(Apf-s{dAr@i_fnNP;~k)d1X;6++@Y zn1rMP2L>2loVEQKk${dtxEo!8-Kx>S4@*TvXZhnM6=W69q-yH~CeHy52@@0WoNaB; zRvZd8rnU~iV1ZZvQ6?xjOM?RWjAgN&;E#xfpk+%D3qdKC)?%n-Q|Xsr59DN4JndCn zmo&!M3S=laoIz~Dhl@|pj`-gNU~t?^@Z&Gd*l(c5omU4XUdwKaB={qSQ^e2(ze@RK zy^FuH?3sg88@QOo%9iM$e$0M6)WBA)ocMx7j=E(&i-gH)H7mP>@>0aIOxP7Z3%QEV zQXqzcz^&8e^S6_~(J)u)O~8(k*jTzeoi#s|G@0xgqrg)hR-(q&RAqm3W_RO&p!gfTzdVrN4IUzY!EW`kkOFd=F}s^%E|TwgJ7{aj8!bOPhe11LXdzz*!JK%vx3- zF~xvA5F7`slPw2W$h%-|ogG1U6g--HT+vp*#_!<(f&(jMYh`P;s)hfJ{DK0YIu z{mv+@?uUK`b%Zc!nZ#i8#n{T(5oaiWMsRTaKHmxe|5GeMn5aLd$g&u1xr-re8!Zz@ z!p;t?aj5m5G_qC1?rhyjA2UT}K>qHga;e z!*KAa0c?Q{0!-w8c`6ttfW#%l!NLfGwx)KAsn^-$b-blTe7M*3^@IJs{3-jRc60cu zKcm)d7uD6NzO_C#Ej{tKa(tlGJo%5-Suhf$kW>o$_fWU{MgKn z#z+KeOBj_42~?Ye1T2(WOgc5S+I*>^e(>V-*Yi$e!i^Ldf0i)~tjfUd^S9=A-G0JL1Zq@!zM;YohAIpTncLyehzCpqeJzsxpZt3IZnYiWDpRDm z#{z=o+Y>9)V5R3AJ|xoV%CI@%)Vj^S(jM!5GWkx&Y!l^+oiS%BSr?r$P0eba$f`ST zYcB8Sv`b|XwYltDtE!5Mtm=Z47k!It>7&PK#~=))XD#m8q+;i#nhKL_ONDtDyLx;U z@8#|-LYo}3^{M@0q(he$zYVT&?F@zR=`GFW8ec?Xibs#+CK=AZu8O6VK>J>>=0X|D z}h9Xy7i<=v9(<{<#3VD%sjRImT#?P$bK`EsQiaFhJw(?moD?%i!(|?(Xg|_~0-T{)X%nE_B5(S;hJI}OnD zTNK`ielg4TjB3XC1l=m`(2N_D_gs4YcAB(vUsp%z$}po$rK~x<{N)TZt#N9qAa>0J zj7_bvy^_jJldW030$PV$EBVUO@eMy7>$(Q`^zfVN*HAFH!w~c}U+T38#O)38hQw`d zc~Inx;ji?{+zYp*wU3pmT(-n|#3mVKtR6WOyMN%dl~76_J-y?aI_A)l9=^M`c5UuH z!L=O;L(LgYwT+(6_;LXLaP9vrDN?+C5*-l}g}XSyMl-&PZ|dfG^18XmAaSs7*0t|{ z{SHWay3ok`;Hppo!Tyki;!^VPft22ITd-g)b~23L(3o%7??ptFQ#AnnQm!ht3?k=3a%;3>_=O zc&oY0Lag}SqnV%zsvUJQsaLFy3BeN~D&|7wAhoaaH`5lZSp`+$o-Sl?UB!5`eMJak zc4eE!1NV>+Y$Kw=zJMB)4f);Qh2fW}#1Oa2&Sf0UN_30>i;Eklkm=+ljS}^t1u<;d z)M=0BgrQqRUD0z&$E4qet~qEb5oC|)9%#G|hjoRMxt4oPmVzZiUSB}DD8c^}c!@%& zp>P9pbPePDXlE-pKI|>B_?#j)^2We;6~jhnkw?dbfq?@7pAl3$v2i2%V3sKC`Lugv ztWON(|F}rdu6~wzb*&ju^Vv_OV|9in6DoxNa8+JJ@s5Lnook{Os_C9>d<9A`Ydqbn zg0DV~oq>X5FulIR@``KEGrx?QA$680Rb$XF%q^Q#V5nigtWQkBP2DY*7EWCez3Utp zd?JZSeJ!XH;;gh`48{k}0r5+GUrZGqv;|f{tOj-rp%XQM>wq7`@2@~&$arj~0e21! zf-Y!A{sevv>5a3$)NjtY8h{*fPZ#DR=nr_};*YDu0TFfJ9D6Z7@FoZ$R+O zfCh4-s)?wu-6s`}>`$4etYyqd;RstliQ4D#8 zQNkB+$ObD>qVDXTUD!=0goyqz_q7h_NjnDrf_AZU~7b+CrRB8 zzR6k)D_9Y+oDxOnqY zi|M#YI870rirmkLG!PP10U_}G6^=hZpj#iL5(s(=7(VCn7E&ERZ-|7nC!#PQ zp)h0tzc9cH6mh^}=o4{IlOF??ncHY+&&7ry|CTphqzeP%NR=~ZU6AF7%H@b#)a3Wd zR7IX>>(euDUa$>ZY(4&17k6T=dJHCXDx}tJxv1$Hn?(s~9bmZd<&9Fz2<*lK*H z)*JkE9^;MbmoCu#=}P}n|HAyi$s1l^QIELtLo+AY?EMJyhvWE5E$<-LJiBNjk~CeJK^2A4{OVY>lz z>KzXr2R@3KrpYSmr{V`cCpXD_w+%0$Z{`=WV4ZRKB%aPV_|d4VO7dV$j z+H9#>9j8OwU5j2_yh7Y<7p;C~FdLf%o9Hl4Y2n~Db!r`VG~$?tR)Ub~uDM1^+T>TF zNwM z8$0EOxz@NM%b?#vsqFE5^veaandwgZ$4{zZ3LKvmr0~*th{+db+WI(5&9FT*1M$dU zZjwvp_?X>7%>zt-t`v!tt}}dnk+b{7nryw2cqQacOf555?sxYbkRF<-ng~t4Co5kQ ztTu#NkiVBKQ@u5f@gcgLu7Z>H`8D&?I#=u2{((rv=(nm)5@XdbdNVH~wM6^$(0`m2fB;r%TDqZ5B$g4!#1la38)tfKZ?A@R0;A`pTrN?1uY> zwhURc)Jnr#kAIeXunVvXmwta>Pc-RXpVmSer>9H9toq!RFLqEYd~3mL_iM501|-x! zN3DV1AfQ%TuYHzvcaq=4vl*QO`4k*H4RGA%5lm{v)X8P%+ar>W60?Z+DgF@t zowwwZ1kV@1jMjq8HA7M^ZMnN~H$F3$<=M<(d=46kPSV~gCdY9do{cL-%!=it@sd*w z+Z!7w7AeYZ{Bq>m_?7O4@98!bL$e4!re$HLHht6*)Sr`Wiz-`aq ze$_RSsWfN(Yo0CC%=N>oxHFSmRsXNlQ1jNv0Jac>Nzs6K|(l>@fhp!j1@)O zsirSk!E}%XF)CSA4B~Ss!4$yiqG2od!yN}k@x1+;R=3xi3;x@$ zzROo9?+1w(`oICgk!Boa&B?6i`XhrH--a>mZO0oUfeEJI!%4qtL#?Q6P#^8U+s}0c zS6{V4AB5cmNZio zeG%fY29{kaqLgu4A5jqr5& zJV^<*BSe(%I?-_*T}f>CQ?R)X%yT!ofjF-L^a~CQ`zm6LMWWHAdWUPnj@U_|>X53* zy3)8fT0frWrv~ht>+{cOfv?Rn4w|_|K6Jxc%>n-8H6uzY@{Qdl5eOco^GZdoj${Hv zSB{N@40oyk91aqpYZ#MNL>7$zJ{PNDir)uU_-H$2iuT@4Q5DgzpNoG$?oUm8MNQ^l zQSE@`_^QOgrUA|%gz3B?s-hzKUB@8pA-D_MnUBt*)5$$)Bn;ZC2?{RB=sYweJmheI zP%A#>)o5o1)SUG3z7vs-ZLR^zj>9c?fECZUptv%HrLFh(G!`oN03D~9D9Hq;nmymC z1zuRlxrSoUY>Y82x1xGMXPBdG0HJMzA|1}LyZkAjhnRqxg(gXr2d{b)L!QvcH048_ z&MorK4^BnW71H|T<0Kn+#76{4k-zaZ#I zoIomfg3fZ+Ny{x_8Ws_~iWjCF6~YQuJg7fQ2BhVY`8vxosZYcGFjEP2z4cZ`ADtH(o1m`*@hD_@eyl47pCc zqI})!6NAD$qz!GAOn9dX(ic+|^xenzoX>omo1p95{vW8yLjdt`J z`<#M36^+on3la_^Ry|Beq)nU59_-BSdCoZK55P@}eK-=&10co3OsjjGW9CwLF^UYZX@fNqrJcQzT)}QYc?)g)RfvmuFfxK)h1fL zBt7YpgrD0~4@2%^s=U%6%B3TUW;AZJPRU_Oy+e+sG1WqgCCAERVIhSWkFzxFwIdtX zPc1+BQ^!kFinub9!P!R-kd?K*GJ@>6RqYINxd^GeV+EVI$;o~TLG&w{K5p zEybOz>|K*%ByB50SbO!z)(?bj0Q+8gX5(mPgcPal6l}59_AP8NGU}#EL6pK-ayDh? zE;}nFIUrT#Na*Gx{(=RK|%zzo)mn zg5Ig3o8kgK8po$K(#GvnVkrif2i4gl2luEI`M586lw`bL2t4BE$-G3m5(_+a+Y|{O z0~xO}GGF7*$<)&dB6C8D)dj5)gL?`k;`wt~KAW2=nwxGxM>l-V7%Iv5r1UcW&J5G0 zT3C9?X3`;Q<;F@>U)mNr$dstY1#6iR(V`#=a<)saakH9-(o`F)qKi3KXj?5a6{oyb zi*gNZR{Zrk8Hg8dB!}fHl87E(+75>t^9DH*N58EjBcdqF3V*Fw!p*#6*&}dK-ttsV zukel>v?H7!}RNiM9e{BL9No zVB-7G0^u3Gom5Ck)SHeWBn{8^bKoFSBcJ>OhtLOfJyi?r4POIVCQL_)Eh*R^x#)Dg z5o+Meg5xzwR9fYdon5XWbJUU)OS!q2hLn=m#}KU_sNKlijXv$O8~B60ul8raIIY&@ z8>o>X{yVE+ZUR@3yAr~Yj1Kbq@?Mh8|Mv8Han;xFs2p2y817@I2&9@8CAD9A8LEl#j+3=)~33=RVj z28>ZD-zpVP?0xtU-u9U(-5%$f{hWCpSJEcm?qj9oI`|#L=CdpP!PA_w8F8D>2X|;> z3ruj)#2KCMCJJmrm1wNgUE=t5rVwla#XbQk!44EXhmhAnNh07d4KNT>ic-pTN*@CR z#9bHya;cLNl)gp9uo+@=7E}j{WqhFi1`#-cqk&ikz<^{1{HzNMu|wJZFcV0>p=?!n z{NV=>00Fnp0%A6RW74ZER7yl=9wRy4xSUFXXx5Gxf@Lm?(O5ym+){wx&IfGk2Ff^K zb4%Z}>8znZW*k@5Y@a4W=vO3+wBW3g!Br$@HtRXkV|+?eqz30BOGF`eOMpVT5w;sl zFJOB#_ha|^m0l=9^4}?j&*N~Mh4t!Na#ANy;9GJq$OoI$!)iOBLZ~(bq zfB+6PBAFmG#vj#OkZg^;R)v9NLx5Q94yS6kJqU=nlAbDdlx!`y;m<3fU(y%|u~-3p zV@a8-L9Gj6pQ;F9$b^tSRPRepI&-D|UMWGaGc8GztHhSxH=%(eu>}<;n;Ws6E9|HY{K+PDF2&sVGgx|%RI*owpQd_kBhVb}0_DX# zf3VwB_h4Pu0@{bZ;Q3jTeofmtj2yBf*na-w)y{_3*xjJhlVH9n|W4xBpFE7=X ztpC`y;3K(UEicDVa+8nZb@BeZPF~llM&HtMMZAhq?lw>FNz11eH;dMqjA3pybrXJD zv>(aqw7(*)ox;u<&p}MC)&9dT%j}y?>A0Th?5~qwnm2&f8UnLj}c$-J1`X=Pt7Y!vRgRT(&D%}zj5__JMzOP>x~ZiSA?vRFBL~c_5}n@Q`y7OIZ?VFx#q*ksA7GU;NW4+$sK=69d}VH5Q9FQZ<*;nM*&b#j z)Uut%$hNZ^{C#*JAYVCBeTaR7N*7eFbr8pxylR52qN1FQd(vnhrt2?rrw2Rjd1BPc zWZ93D=v4l759xQs8*j-)Mw`o47}l^7p9lja*~r&D#70R(rl0kW&QdPPc8#P&^2`Rk zgePx}4iRW;>zmZiHreaeIF4^t_-|X{P6#bCEB7dn1+VaJs?c<=9$OB(ehhC8TVw%} ze!t-@XCChAavPOMie4apSrvotj&Ewz2qP&MS@KhO zK)947$)aEuS@0^E2{BoZWbyO?+ktbKyc@?NKvYN(85;;C_E{&5X&;sf9Bt7Vz^pW> zlmaZItDSJ1A$-yL_T*ZKkm~w z*TX7>AU^^Cmm+!?hp{dkCZLiMEP7xtPR2e{OAkU3>&{%$imnzqv9t4XrMHVFqtM8| z`;w}@{*v)$Bn-kue%3PKrJaUqOg*zvqCdWWT+D>jfxlQ#v22Lbr)x}u^OS&gZnC%aA;jO^{R+*VCMzB9mVwkKqsCN3N`YOl za_(01t))H}zIIv-mYlt;A7(bJEE@BJ-#vKE!{U}PQlia&Dm}77hol9Pm^hVcGZx9% zHQ6@Cny=VbwF-{v%rPCEbWGBuTz8cW&%1r;x%{QBX~d8d1tAY?}6x=;SCRxLjS2tix zj@axnHq#r$w$nzVlhTEhpnG~DR@b7}7q9ckqWeo`xA{HFdVXRwn(zjjzbu*wn9Qtg-LZCVp$UD zo+vbCd0C9ce8~|s3`0x?W{DBZ`Usw0%PM(mw74jN@Dror1zN;Nj*DNMr2Hs3k#?fR z2nmMO?RaG0O`>I!ezNGwCvjCPu94YHQ6HJqw5YyHoysxZEgae$uw#_=pGdncuQF)6 z6!jinEwPki5Db;sd(o?vj_%+W-}P5z_GT2;*EH=`KR;^vzQ8rf=&W-({f2q_g8zoJ8{$1s+nYR5YM%vC<`lYP2WzT%<1 zYHi*&oZ{ZS(F^UdY4WQkatX?vBasI+?U3%l1l}~{oGw*wHA^*c9<2%b%p_2bJR<^| z?*1p;eYd8GE&IhN=M1scS4>q-YXa@8@4p64t7euXo6RF{0#J1G3TTlr`0O#-O{3PU zRa2`DPu~Z6X|H`lvJo=Y>Rd(_pC38e+xUpEBW@Y;Xx5BX>jh#pikA=R1~N9!X?dQ9 z9{W%e&EI&*2WMU5Mt2>xbkGq?RqiIRbiog#svD0_JFuEwqCA|X6a+mJ zj;`~XatbJChxxrAFBA3&$Iqdbt{-e38LS0|WrA$W^1M(#3hWjNDTt`t$tLnol+m)e zL6t7vv*`;%b@iIx8-Wpu5iN4-ENNusG)|UmIK3~ zU$U_zt3)QaK^_w?J#NH&U~SzIaPkNiLEAjYRiYVWdSL6v3-kxfUD5`G_L%p(J zx%7d+kZcG&03SV;`VTRdArQILxFi|sNxURE9-t~qBzM&ynuG!@OvtNapj(~x1WFJ1 zJMJ7OpmmhYGr}I>nk62}8eBg!n$8<)ni#}6X?SibD*=ldu7{om;FeB9D1%;tYDH}M z$Ssf1JR_d=q0PyGbl)bz%ilV`T{3fm6LIaUb0nMECBHo*(?@r}04X=AA{aM(CcsBh zV>lSvS)N60E2%(%EHZpd1`U-T%m*$L>g8iJ(RFg)>An?6-alx)9@EDOj+C9V4mV&_ z@JFabI1vRQ&fM5kd?IleFmVIN2kUnla-a}gD{LV*B@Vm}5;T3E1s!A!&3$+k?ni^R zeCEnUgU2AtDNv0x4+UB=c$SH_5W=E(%0ch%I;3tJre(MtsK-rZojwr3ScfmyuMRK- z6G^<_&hX#}U7W7ZBGMAfVgR? z7mrnBl`v!2HRQ)&;%Y#Ts>G7P%1+&MUFodS7&FxCG{3~kiQaM#8W-hR>(S19L3Ix! zu|WP0U7?1V(8FA3dw{6}6j`&>;yF3x`EF zlto}bPmPE$LP-pyHY#aQGKs<~f|*WBT4$V#Vs&i5BmTZK>sZhd8X%z7H>kv-N5KTu zpcb1V#iCinge{q9yshDp)uOjXGDw_0>8sZbVuXnWK#<@bQ& zmt=HVJeopXHL0*n`qFQrGm@#!!&+Pto@t6R%fhb?)Vyo@Qi>eZR>`m~-;6wz7r6zVgR;sq<}>EDsjBefN*uVNK5D0%ok~Y2hKZL#v&+fxR0uZ?&E%(b zvr6CQc(>o|+}5>DCsxpo%6)=L^UV8x_iS&v-~lC_p5R(*q!>n#n$nmd8STT9PL(Nd1bHn1*q^taJ{_>w{LDdTgE;qA(0 z`f+%4!fJm?Iydw&3stuS^~(%`%Ws;`-_uJdXvAlK^oW+UCdYN%t=2q+dPt>hJ$FSo`>E8IBgLqqHi~4oTvNV7JdM-M zX4-%uSv#9%$4Hy0*XrX};OPIPkF7e%uXcd`a8HI_1vrUC(zU5l5iG|GkH<1kIqAB3i=gsL zv67d5K<}=mlQB#vo$4(ktor6SwJ_Y1<@2BwN17ULGS$u{k?Hwe?;-NeE4jE!xTj|P zQos9}y-BI*+(^k#%R!B{D+B9Kb?nbuUY7AFcTvbLdpi|gGsE5JUpNcOkd!6#X58|8 zf%(>l^B1P~A?>w(&&yKh>}OjNTM)w!KK_K8QI+^)%4~h-%V^BPL8ou2Z_Yp`=Hq-* zb<5{Nl5I2HmeIGJuI;P*%?m5BBo?^GPmu$&?yF)$Y8HU_BWf(t$ZyUssqi;1H*fXN zY9VRZZ}^397RCS0+W+;L&HuHvXXa%22X9~I?dFZ%dv{y3e!aFVceZnCn}AzYcpUgc za!{-Tf|zX4(@joT0?-p!m8*>Q6Qcv3#ljE`Iz4}rdG7C-(7jE z`>mZXa+$lCk2{&U?(&*b$o#UjYL1LB*<}`zwTYry!emFnV3u7#N4VMmSF&!t95Uv~ zF-&804>ha~t@~hC!4`R-2w3KVCdi(XDxn z>#fNbi7Tg{iI}=*a(Pd;yRxTU+HrjhFj0bVH7%yyo{8nPF_=3*w29m8&24ly{rPlM z{&mKyM;p~yA7txjY5Xj({Vg}O1zlEc!qV|=JokxC=Iya+mT5$?Pfcc~!~YWm1}m}X zQ}DAfgyWb@%0tGAnQ)*5J%u~Ll|Z?U!(w=8nhf@n0Z}K7F;1YKk?Z{#R4Bk#^tnE9 zPtrIIuHX(bup67AAwE+C$)I`w`&y8K;$At2peMYO)Z6pC{V+J5TgKayDiQe1G~I<2 zJvd_GiS_NkjI1aQl+1!Ji~SX`=&M6Q^<~T0tIXbO;U|>xEC*H z)eC>SN&c6zfQe&m>Q4&w3~#r$={CKi=(RI4$8^)i^a!H2r2(JAEwoaGn}Su(^v6Z1 zGUZ@ueg$X8ilCX|SLa8%xTMpI=zRBubDW0H{1T? zUl+m8K0Dtgz0R{wUduKd_*P=eN2*P_@|4U z+U9qoLCM;E8FlMfp<2;j@;*ahfU6^>uR@J@-&-6(@4%DaxbWV?;@rT@`zKGwqcU){ zzs%etU9nSTTf4!s-f%*E`>|Bu(VO&Dz{&XfEe-eko0Y9W>|_o9kxhM~7U{s^XUB=9 zRnh4(rB}aFuHb!nqwtGV=#8m+)9wNCdjSZ!t1BZup5=g1aK^*I!iHnd{ggX8PUKmVaF#zQP-hsR z$h>418O8_yy@G9#EL5Br#2E7-oqgfK?E;%MSO+!I=!|@`yA`egkDG+wnv7Wr!jmqs zZ#yAii|8XxU$jx*S7?{70TcZrX1lEQ%x zaF?)=aDqs+@CV@`5j^6tcp2fIcv_Jq;a_my@JPbah^Iw%Lsw87%?DnHX@%!PtPwnD zwnO6Qh1WhlaBdIBp9$ZF;vqb+Zkr4&PUKF6Pux%Zo>-aKoG4M`cb2qp+BeN36{$dM z<^Rq48UEyB7CN`U_3eb0aB9e}4?b+pD*LQ?jA3oqk3#$Ac|5{yVXt_P+WY!>#UibS zd4`jQQik6Q9}G%CBFcoyt~b}P0}ZzvFo5Bo%VEV__OKY?KzRa3a+Xf0MJjceZAF=v8n);z>9=bB{` zDOY>5V79coXj`*tqiw1E#j9txiqFPt@HX_sXSukp!e)K>b`fzgb_v@0EjTP#B7`#3 zJa{i8HFQ3BK1?5N4ae8xe*gSpBeAQwdv!yldoOq$&sXBUbpt850#2XsRrKCzqawH+ z|JCq*Z(}|94DOBm`R;sc!%qSrx&WFfpST!u7MJUZN7Ob2%om?ye| z%uKpj6s}Er8mWPDq1e+6jFYgAaA)4U3BM!ZkGQ8XQtwd!wu|FMaH2cBzX;F5!a~f# zH$|X{qKU7G>0xLhvwc3G^mU7bQruPS@T;}w{bFC~ zA1n5!nJ1a0n7=VUFq<;hGJj;o?1yDm?}?81hCEF`+Ka_JZDbp*i8W2=q(2hGY-P;R z!;5|8JyObi*5i$KB{oveEYOD+{y@4bI$~gLVC`?l)N{8tsWUX>sxln4< z-=~MkL#`Hc5|M??!+2Y_&}^LA_bb|mY!3Cw`BC5qa)q4MF6d#%wn=8?6 zPD6adkA|Lx=!TYtsfP51$A+j)tu2N)T>MY`w#qtgnLM_ZE13-$Tc_d8pH2fB*d30x zvctWYPj4FTHu)o-Xl&J26dc<7@FRH8-5B^e`C0gh`T5oe^ilNj^)dYny=9)y@0Bi$ zHz|AS`(-Y~pMT%uZejM_^{->T89XoDf4orW6CixEeCD|z?DYe_**wQxz-+#S3jhVu zkkgQ}kyGQ-;}aDV6f-8$CNk|kgtfa|;B?`{yP|_1;M~YoGAc?707nEAFXpPtRe_(f^T zM+%9YFa26{3SP>N%tq#s$xKukiz5;g!UIJcXX1cWkgN#{X7+F1q{x@EZhoBuR_xyWe? zi3(W?8FspoQj#{Pzbp3@%E}%{PpUjBn-$YZY9>{4ntBW!CiN?G6!T_Ov+tBA*-$U5 zxE4LfR}1Xe4^<_x{*<-Uu#~lQv{bVcvh*k+o&Dx1Rg&guYN>t5{xeZ!=QFE|=i$nX zw(^;5tALBxVbe^^Ple*Pq(||?r=K}RzFChxhix+=KP6OPl;5P_rJ|%|WQQe(WoYF} zrAif=smj?;E`Lvc*_x&(bSZ9}E-D(8YUVnL{p~ePAgP^L$A1#>dv8il%8Tcu`}g>? zYr%>16SIxqQr>TY>Db~dd7e~)G=da@WP+URgzRs&3XIZ>3Kdd&)40=&@^(^$DZZwU z``4w@6>@e8XVU7^qt`zVYNqU@_0!s@UQVx{rU@nW6WjP-BChwQ^rifGUb?Txr`x60 z6JKQ>&kp*h-^O4EDouOL3QSDQ(ab)ZRAR?qrl z!DMbT7Me-vls)djzL%95=h!yzz_Hh#3CZQRojHI#@^R$jc+9Ze=;$E*Q2EG?BjbS0 z5Ppi6>gmGDkz?_8Nh4n)tJB`jT8fw3>C{ScW8Aircy#>3vb;I`gSAU-v zpVk++C#PHWW4mR6-+s1leQo`(Q7>*!4o~YI;2w1?3oS`4$1Pngk-Qug%x6RMsjyBrfH5 zvWAhy;zkq(6vpfKQn%Ij=6Ced))NGH{XV}oJV!j}K6v`-zaBqBJw#n%?lF$*XT52> z?mnAe)$g_^x6}K1y^cK-Uf%5yjtQjr75P)c(uPw@G7QjAQBg74qjADBP$R?tqO+iF zC^B#i&@sS}WlYnym+8!cy2C7^(onCg0{slc{GdncUJu#|WQ1>{UC_3#1dRtKLYcz{ zeIWg?1wZ}42|fzG^ut3JamZ*$DtatkOVjyd*O+j5Wxc)H#&g#){28^5T0_bCWS3mX zI9i*|z1ap#NDlfb)r#(W$8Q(nhn~%FjS+$&hDnZYim`*4j6RFOj;5fz-1xBmNwbCS}*gD3GhI8(ITt2E;P;Wr* zMz2Hf&t9%xvEJlfoeQX5x!&%`3K{}!Z{3R|quPdIce9I@&E?2520g8o>ie%o3K!G8 zjOgu3&%PJMz3*L%eoMu@;>F}TNFgrDS2(zXnZ-?!HiV5H}g${0QJw;L1GrPml9Dz~o^?4)m#o|P}X1}_rYWgw+( z3abjK3l|GR3egMSU!FfGEEJKENNSR-p@X5BqL`v*#z;$D%1}z%Tv=9V?Y{V<+QAfc zxM}FRx~+QA6n+RJnVvygudeC1s(RFPJjI6ItJGS1@wPh4R3Pbukw?e1>{ymdg+Pr! zC0i$3RZme*@07|dMPHdAMPGAG%~$SW+p%$lE=P~Q{yF86XZVa!U#abvxAB9@4r5Zg z+Nb4r1`e)U1bP<|#T82_AO$V3W8}ux6 zEit>^vd9PYdi52Rsxl+h-tXw+sx8VFuDxOCIqKdjRmGdBk?XXv>d(5^ieE~j%VmF# z{Gux>`(Z+hOUqb}r^S^&rRrg0Dp9EHA+i%altE)x-csr)wIh;@q|UF`Sa{hxG*7!; z`dn~XI;5K{p!%xiQE>Trr?CW7GEfp+a!uoy4JWIdXjS^#3^OA3em4|7E+lOU` zfrpot616pt36@olLx**TRwb0`!?R{L*N2U>^`F-@ef(}B4_#()OLIzm^B!vt>r3iY z?JCwZUqo(R54&gkElI3UET^oF*~!^w*?BBhB;b)fDdbrq5fgl|B^gmZs~n3(P)iITh@F9&KC#Ee$LMFI{VS*+|*A*yx^w z)Y8{>TS?5umS$-ztCr5+&W`=kRc!v@>Tq(oG+P@tYx~Qm&eiHfyLS0~xsTJbmpoU$ zlZ_?gT64T;(h=a6q}w)UBwjM&m_y$8Ugj0%A?CHo(+NDESX}%lyeRx({8IclE)Je- z7i*W6orT?n(}jck&Z>2X1&0xbP}2n_j!-$XngxiuOqWXeTNE{u3X|mptA)X`k@RC{ zR|YS5FG??g=0M$kTaz3keFJ^tbyESec9VAFyK0z4fyKmQO@{C&&}JhWLn`fV31>EL z7rRrc18HMv<58o${FY~<=8E^J>nVXPc73E*(sB=9ck4*&pihTS-wDXoNx-Sy!Ox+% z(aD>MP%}qYU+E;fgMKo z>$CmeG#s@YH}UYZ>C9Q#JeF3(c*t~sc@t;cQ~6r_{K8gaOMUY&)%-xzd|*CYK6XA- zKDw|!GW`ZvI-~_+E*B>(K|W$WLB5bbd=_#8EHBJCUWXIdIQTo!c+Yr^1NtH2pa|f3 zG2E>o0ZaY)K6HQ8VR#V*@%%Z#9KbfgdceaWkzt7bL8!ntZ2frWw+4sw#Cv>IIo{3x zPeeZ~bS7`>a3YYKXa+nF5!OZUhZUZ2rI}2<`&MWB`_6Zx z+!c8^BRqy{aLw`yE?o(zuiP6yP-FiHx*NgC;u>Fq6Jy+4fH8KWPPm4Jz_?GF7vj8Y z!TlNM?x@~h0vY9)<^aZW`-2qja{yYo$|(fe(aNc4`7eE2qwX!(ai6v>%o=6__q5J+ z;3u^G*8&M_1FA5vto|O@YI@C4vt|S5>N>_T?iW9_sDWxBD$w1_JFKAeXwS6*=Kocq z1XBRZ2IB>Hhd2j-;5tzK|5boc0A$1R0^Lc@ML`i@DBxrel7M(vBA_6NzbIG)269xx zILT>E_>(m~OsB|<(2NM1ASW>naXL{tu@;dQF#r}sd|4CzOh+ORH84){AM^+;8`2%| z-<3pFj**nrz#h?casN9Cvj<$&6m`Q0$P^d-3c7#^%bEkHHG7;fn6t`Z6#4v- zM>GLW7@e77OydCE{-m{9_*jJX`D! zx=4{Go@ox;`{NKej*JN?Ii^*B0PtB8;D^zfBX(|{5io%eY)0e{)L?>u7dPmHrNaua zfhGul4|=TU=>hWyyz$WRQwBmfbdo_(Un+?{Vz6}vQfN#7;L{C+Q0XiJq2wxa;r_k& z=N0~PvHvwy0}ycfL%~#nz%cMS0wFc*!Qc@MI>F1RT934+kl2*-Ax()E*tK2Y@ zJ3(_DB-T=2=dZ0z8aG4;6K+}_4On)0?t8O{x-`}l*QlTJ>6dx|yHoLmI#;Q8M zR6OO0fAYpL`+-77?K{fS8jB022!Ouf#cMyuU(weUeLT?ziiv zKnn3|sJ|2^6C4c1Mh6*QS}qx|8v;@|Cs1ItHU(wyEFvK39dgMLtq>58duAb# z$a(|9Igx=dV;db@c${I7d-fna#FnlAbxt~T&Ix!J&kaFFy!{Z!R(tvNE&txgfbPfu z$YJ{!3yOhI$p5TMgE*1D6K5Iydo{wyq5pCpf7XN@9QKbpY@pav^)z?$a#NsGJH~4W zhs1OMks#{y1VnM#17R38JH-BHvB7LIi5`lrCm@t_0vQHpQ&0qNj^PhTMnF;F%@iTq`}b5d=S%7Q{nFAcgQn|D!tqq`4A=9ABlWTM%@^q` z{hxQVAANfd-iI-yTL~d*qAF}|a-P8OTGlhW?Rq!rH_x>V$9WF#;%=V$A6JcDTs7LY z%hrjGJ`Fs6bo33%TqoN5H1L2s@<8w8JDj=BvRD5%+Op1aRzLDYf8{&evVQqc_viKx zDd$YuZ^!d5fNsbA=z9$<;2A{N+G$t$7fc*{+P|(JKBzyw)^>fQ=XpuV@*S3MH!WVT zp0;b8{5QZ>imc#S2VJRogCV{#QNBG#`kl`@`i9)my7(5ZRj}Qo7wdlk6xh-6;Q4~J zwr%WU2K;PGEOH_z`Py9F%0afQ8u z6u{u3@Cn{Q*2(k2dg+Zs0=hDQB|zwWLU{CC)`v>zfaB#1fT27G0SM?if}q^XMBL-S zkyt=N(7gG4aTepGOILFIv=D$zjKA-O-~MOGzo!}==kI`h;1zy`FuE{J%nZ z+uiQAPwED4UAnt9`^AFgX4Mkt{~4W1yqu9R5*HvU0=(X!@9y?!NU@upBE0TD5Syi4 z7F0__#P#>iv#O9W0tH!=CFl=KlsPRrrvkr2DMWE=%}nP9V90B+P31>mjQ+OB6QiXE zXeoL@)KdOm1(I4yWv{;m^RG3K)CrK(C_p;EKlQcV9NK^OwUa2L9aevD@>|S6?2r}M z?*B%j@2~>bgFn~upND9{0M&w3K)L@Lsr(GH3U@pfmQOX_> zZZFIxtf8ib-(W6BO~MJwYhE53Vd3Agg~)6B2MamJuFnJ z^G0hP36f|L8Kj4OAt)+$Ap)K^A?nS8S0K8(bd*Bs;h!J+tN+of&%R6VU3m$lA|LW$ zfFe?`C(#UK-k)X;Mwm}_zT25EUHK1{t-~2o_S1W?<^Va2B&+=gV%0|e35cDMd7_*| z8nB3gVLyU?gjx9iQHA?xc9GwLzlC9uQU5m1!36e`v5L$gmGC%>lwJ(;u7C zpbze*!wQUGH^={h(%=>DV@Ed|8jk-wSPL|W9Slk3vjvzQrc~HnlujLzG?{nteKkxuF`RQc?S4*k34}sw554 z0QCq1O5ibBV3ufQBCIP)r##7m6oBU+MNLA8C9waZ?BAa7&*J%4SbmgF36gtB0AU1( z6o^0;7$C|N4-1XbDM*4P34n|+AOg;i20Ha{=P=*Hr2sowNHoL&!{G+lKswSuQ_;$3 z*#CD?UGzK>Ru9-oOX4mDs0at416xP}|0+5^B2SR~568Tp_@CcGm@!}{7YU~XU@shm z2h4oGZ&CYL*#B8HAq}(^jgNt?1`2VI42T03!-;T#|0@1pRr;T+A`BFwB7qeH=xh(;2~BWfQ8dy4F{Lfpkxry>e05=*PQOErKlqEkZ2<-rHdCh!p$3rRsQs_F$dh0GMd5o3?X~|Dmb(1kFNL z5V+rTl!hgHYW)1q@WnqFTH}j<&d2i_a9@s&@&Avrw+xCiX!^YaA%WoT?(XjH?he6O zEVx6026uONXK@L^9Tp3VyJc|+iyiL!srRi@=fnAMs-~u;WgMiMN-AT`PulGNZ5scs0zjhjf2DL7J*?!sYfq_k{#ZDT2*pue3-LjRE z6PeNvAXJrZxmd8oB@1i$2bVjHx53y#mxwcTiqvvqF<$g+N@Gn(XJzflYB26b@aIVWJp(nbLvy#1 z*JL1~P$0j?_#GNQGeNoWgpQWt3qNTT?WfW9}*GQL^p1smOPwK9V4QE>z~YgPi^p5q51z|!`rIq;?JVFuS(d*knnAC zpPzz1{eFH%pp&MO#**feMhZid_-};lzX1?|???X=3HkpQP3$9rV~vZ)_~c()>RP(I z6ay8Nt?!6wci@B2*n5;PSZL{;Fv(^_jxfVpV z3xubfZ~q+hnfm+dWz>#aeNz)KYXIn1l&=aQZ#a5S=JhV!)4Bn6?!f+n{zCrco~l*x zKkZTkAzJ&+oe5JZS@){mksRUp^J_xXs~ZZ8ZEE%fwVq)Axca^mh)CW&Ysk+>hVE`i z;Qk3O?DEp){Hnvse!QwTn{Ur-<1BYM_`tM#Ez?U7~Ndcl()c%#=OPef$jqidaxKc;J@D|y89hRtQ_d@ z<|3zX^s>U_0a{tscSy_awU3tQA>nFiZ_v5`n#n@jM!Eftjef7;ziW5EZ@e>aEZE(5 zqw1NzzOQAXpQ&ZbBM*jgp-d4|=4Ac--hI4n6{YED{0jN%#G2BK-0f46(fF01fGNdnkHo&i{vUbN)3@$@ zpO{7egfX3ceZ}~M@us-Nm(;NYe5m&jz72Q6oEdv(e`}; zsQ08-k|m13Io+t*{vWAR2-Wphw`b*Nlc`0{2h2xYtig4K`VG0;*(lW~yD#&>R+L$M zQLi88(YVH^o^EN_C8pr_!9mdWu}pd>o;NHOENo`yJ{W?Gl{z%UdGqB}(k+Ncz?pKi zZr|_grSS+klrrLrf7rkIq3w%m6`G^7sMK+eJmQ5h0jHR8xG*PbeXj9G8%=lIq*<=7 zv5NKmvNJ+sk5Bt`qViMxnK1+wgEq-Ef>`D?WxZz8QvIjep;3o*c3=dt>e7*8=7 z!Ay4jD={OYN7(8tQ7@uLa6gn{jrFnOF|5(?Pxa)6UL#eShFPp2J2Y#)Tb9gjO^Da= z`Pd;+r3bJ(z#wTGr02O}ZNk;f>mj!G;`tDNp0}~(5xn+d@=$+%(e3U1HrHG6G_9QzK-3%;#vU;dG|8c&s zVcYd~PWo4LEwKKnz`0>a9!9eeoBERyg=Qr-?P}>a2Fd8u;!-;X+32+0QXd8h#nj|d zD+U?GG*GDrgVaQ7bEzYP+(g=6&HPk09Qkm~ByHw2`7+HcZB`xmG|e<^mL+*$vXljl z>Ta1}l_?-GSF^<92e)*WdY62cewTEYHXu2>47W-LlUjq25haB+B|<4fNl#u+k*c(& zGzmm+-^wiuNHGTKp8)K0xlOalO{h$mOz2G5R8nabARwzMsccG5MH9_-YK7)f`RY=I zuKjf6@l@wTzf#jGwQNR}lyW7m(ku|OeH*u2mqs?z2K98xp%PMQPFXmJ1yl!e0zp8O zC#Y3sU0PjAT}EAUhRhpG8+03NEJ^8#lcfiskDyQx;t7R)S*xNUOI^~k;#p~AnOvz{ z*=Xq<=(ByvZO48RuR=~4T`65zMJWqt0mKDr0l9;2KuDk%kP>L}9hHD{qI1G?;(3B{ zqH@A=;&eiCVsavK5_s~_KIgXRHtDwMHtM$OHmlVHY7CWxYC;vEhF}UvYF|=cT3?En z!j@8Z8Cj_aC;?=8LT6ua+tO+Vl@TN-NexOvRp?iUEZZs*D-|oF0%@GEon(3#3sU5z zsw#X0*`LJTwsX_xrOhb3$(v>+ecTrpkVj3I+E*7)ZX4fm3nONb8=rTJC1x5Ozj6!7 zrKcMocZ<$_S1_NrMdUKrj<34K=Q6Dw2n(38CL$eBcIvYxDIIWj8rLT>9WZtp)+aew zM@~)TPEC5c^{$f(9mqby`u+?k3P=iQ3Wy4*TBqilWO1uu9xE2sCZ#o_May8zXh>{G zl^fF=r#jHMw)2f$r|sTvx?Z~G_w5mu=#%Z!?NjYD&8JsOUOO0fixieQr(R!XQEFyp zYF4B-qZ@Ca$hk&wOIT-m7}q+mzxMEr5Z214nN2?$6_JK93&p3Zb~6W-H@s`UUR^6ZRnf# z-1z+Sx$-&lKWYw_RI&__Yg*ry=dkC}=hPmVAj2TpAl)Fp#0jZLOE>Wh@%^oPm*G5Gz^>xOHJN503#=kDjo=ZXMnQN}kK zvXq2Ly8V=E248VemV%_WbohgoYk^0y)f#ri@0gWv3GX$+$@ zEYkRCOcm5I)2L|-6f`u`xM@tr)j89cX^h4-+;F;+EB2W_DHds#Vl&YwR%w=}GT|te zX_jd-@hH~qs_Tbq`IMSBhjU0vj1ZD)1ARMRrGtZHSgawe|StO;i8ws#(mMpn&w>6F$X6H;nU zTKL3!Wy*xp1Z0Bp0JY4lQ>#;{)2LI!nbU<=oav*XLc<|9W=ep=R>ALAU>bmMWtJ&ny_)+pv^HK59 zaJA^KcAv)k+0*i3*kbBVBTE&TNSH7^ptCNxZfQ1qlo2Q-)(+A^W$0&!OxsF(KOt#U z6B-9>2bpfh0!6vnstg||>AUeCcyy^rHkzHj|wF-#Ot^qFz^O&)yBP~$^^;tBOmNm8c#qkxKMCO_73)4Wm4pq)G$^S3u=>; zo0g;MvFSCaH)zXM>QzxKX`I@5#)8Yc7Mo6&PWe511SNW9dv$wNdrk8yRW;X^#sQIn zG7#PFz&BFW2UO<7MPF}gHo^2)9lEJB?XS`pDpkA*+Ud41gq232zZ^ zDPu8XsqU2NwC2>|^z4-AH0RXlbnR5=wENWm^yw7-l=n{Rj_S_x4(m?qj?1$f+6fJZ zmO;~?z%Hqcs-TjfnxKkv&3--a8nH_MMY5&dQ?*mkJ6q3wXpEn@Nabrasb;ViT1|gV zaAk0{++xY8*(t|eho7WKRlX+t;=;Q)-^Ej1q$XeMO{15vb>WI)*^qk|h9Y+!BA>%4w@#orF6e4*Us>4v~aVLM$Md5Y0LThh@W7U6na$ zr%GPsZe^l+lX{aPld8D6dXOxjq;(#QU#H@3Zwagcx`KV2LcHR<>b&y2dU-W+N`Ve3 zKvbvbME^e)EiL-e>pr}(duS!n+^qdW#rF9id43TxJ_e$Ya z%V}Vlb6&;;wA-}<+U?sNVp@e-gCMF9R){l%^c@`0;8oz&-zIHT&9ad0fM$mVU}}wQ zO#?GJ0o!DaYU&n9mr3VImq-_u9f(@vzP3s7QNDJ zOOv;5y^;-!HMf9X*@h(&!5VkLhLw{$ztHnVqC2Epiucng109CaK+E3s-nH$=bzOxq zQ1!sfpe#}2e&c@0eoe9>v$BLmxs#GR4!@jp(CDe&+1~9H6z+xa#qdS&#V@c}RKaD1 z?u-PA-K%v0>h@H~@RZT>R9W$CS55y1Me$46ta&)my0eFR1V)Hz6_m{`A06|Zy5Hs8 z`a%N&e+0GksrSqD>-4Mio0yeu6+N7JpL(BopFJGM-1*-<-9FvXKs5ui`iz6cgVoK7 z#7Y|$^-gN;c%X)Xd9RJHKVK_fGy6=p3SAb-Rz#q*fi16Lucfc4eKNs@!Lq@+!K%Tg z!4kn5!3x0!Th;x={nh>D{q_At{Z;*C{dN5%{Wbj+{SCo|E(>CdVj!_)v3ap2v4!@t zf-|#Yvs1GZvooRFJSZQu9qJ8been-$e+})Ed(+sec`LnG2wr|T>pzCS4TUy9DPH(q z8eh9#BVQ|mq{XV=%E%TH&ggDapbUZHVs!=cZ_Ds^El`0MvW+vFb(nK;??j5Xu9- z9{-Rh!Uy2_+4@R1T^C*F+D6I-$vMNhs&_{B8cU~j`>yT=q3@#}(O&G;2;3gwp5dP0 zo}Xng$G9CIEfI-q#=Mh!gd=?fz%IhM17(msjwqJ2WaXHvoNyubWCYo=oMST6X^O*{ z`;d^2;3oEQ1a{BHvdA^YwZ=8awYzDoWAK>ooco;focEjqm*|1;f#88iDYk5c)3WpG z`&D7nZ=W%J`&v$2B8OPuh~VDWJ&Zk#Jr2v>rhz|p!p=UiDkC;~U-lIC7%XG1TCZZS zYOivydagpQim#Hdnwyq9H&;22;L z00^*gS#&@h@Kx2P!^% zoLQXIh|9>=J?}lVJ+-}`u8aRB`E7{#RPpKJv_`(Wg840B%yu%~r5!&ax=awzuiZ`f8JHVAGamd6@0R zH9N(JG$q+G#>}fUrP(sY%*QmP*fLSe>o8@w@U@xN_Sz=Tz=bzcwPn8N7qNw@ovD?n zqp5`{fH!N}CT10YSZ;^P6PcBfH8?#v%{0X{jd7@RDDR#s04BC<%VKq}^#uyd5WA?d zH*hrYG;lTW(PgJhdAT>QepTfVnr3ZTOI2RgR$f|E-tfqYu+Qep6tQVowN>S*$Xb{t zI8=5|7g)=++_anFap645x|#lTIDII2gL|WU!+Yc9p5z<38a!B(67{~7sJBL3>5 zcV4Hc@6&d3QBmmq59>LL&o%{p?7m?0M{(mf@Q>@nfj$Xux5s;}qW#j!{@^EZ^|z59 z_p?tMp^(xDvyH7SvDVrGVH`JeJJ(A8Z_V<~Dx|Sz?ThFkK3l&c7BcAA?l_C`n@nkc z?_F_zWi6Hg{T^vG0Ke?V*EmIGeDRJmIb|EP+Zc13?KP#H;8|u&Ilt$e7Xm|jm21yn zG--W#{d+6yd;gI*nO>OHH!-QJ(k0AV_H2G6RqJ>1>tA__oP4L06s5i1I$rxFEWp2& zpv-mmV-528jL&kJUMQ@XvSI1>MFEC}%~zs>QvB61DX z9mX%q?!1(oy+`t)#|PXAwqNQ*HyKA+A2_29@^P5-e6sj2F48^0d;8%u^OWEl!6jqu z?gU|R7HN!zEbLQL>=fRD^()d#KQ#l-F{(|iWs=$MBVe}z(G{^TO+}rba{RO=Sw}b_ ztrLE$p%NL{ts{-$ng%GEq!eKMC=1PhrG$K?1|>>^KS}659dbNq1oM@Y4n{8~+&Pxg z^37Y^^aJ?;EEaNW*-tC$ZTu(@CVp#w$_q2@k2F?vrP`>mWx;)hRkWC8T)wS+=ZOI{-gx$*Up|0v$3V$c%=0hfsq|+S zSx$`f``!$OBJYT9@a83FUH){Nnq3WF`{1*GBaCKIX;*_I*yfpR4H3fw&#QfNoP8?f`%CO zg>WD2sbf}p&kJNK%MGy#!eg0OcH5m$S`$NtOt_8b$hTi+$WVXY)7lgEKCuLjM7M3t z{lPn|J}0LdZ>h=?)a6WyZLBzHY>_?1HGGyVs36&08PTNLzkMWWMKX2mbi}o zX(cb=OO2%%k?p3=%m>%9U#v=7_@f72?c92OfDC^#JQ5?6ssq=a?73~Y5D^e^@jn26 zu%*D~lX3nFIDW)MP7dDx8xAu|K=pX`I-obZu_##?MDDcRU0)!FlkwuilvYb^F;m5IkPc6HRmw-noN&~Vb-r^WwS56 z8Ihz*m)t$hWRDHLc3dzatNk}`LdRZUe1xPML-dFZp`(Ir-JOHw;T+6K(MxyIXXy70 z(~AaV3O$ERKY05&VadTGhJ?FY9?@yU`ceB2qB}1+fB46TX0DoE3%<$csw%k)+RgcA znu?sgSZ71-?ORD$HT^_#)RWhg37uNfhGQWWmM5Y)d+}C+@t?`4f_!=F=mL+j8-Jub zr9u_ZKF??5E2v2ww@wyP6G^IZ9k+_hmsDUVZ&N9eHOc$dE%nye2}GohdmxPHCnO@s zHg`{JyFa!XJEVfT!}C>Mcw>T(slg#exc2%@QKh;GP@a{eMP`-5W0NzJ*Bui(doC8d zau$e*qEII~Yce*PR9L+5YY%TaZv)Cr6t{1!#DoSF3K%CxMe{TKmU&CFh+d8YbfIOH z{Gi`{%wXP4W`*+&j7e=VUg5a8%lYMw6BRj@(Kl2c~x zwWKjk1&lM9C;^SCmSw3DY)SIu3yeM{Hfm1AR5Z{@{mXqQsHjCy_6c1^stDy7o#?PL zVwsL6Bxsc{g~%7(VTzmu8iG|!9TZc1By7lktSbXKL|GD`c#3Bjgy$8X^^!Sbno(6e zGnHv=2B4oxmu@mU9c+@m<{oc|#c)TUYBG(-+&Y#Fe&br=F2I!}+mef<9W+*Uf1SP! z1lQxMzk1J#J#{a)8;k5?U=ub^R{J?oFF{460PgU*Ks z-zg_8r;044S+6id*InP*icDBSU8<9su{K@XIlF9CDhVj+O0{Rr@*^&MRBK~|3^7Xp z7*UYW-b*@$yVll}Mz*J7T>eVT|l z~BoJtN zM)8T{Ar(V|W~Ak!$BQnnh7?*oo=Er7SNC?3Gv<*!dRu>PQfJhu#0QCysy~CC82$v6 zF5y|hp?_W%o@8`sUFN=V&Xt3P*xv!45FliP&GNw`c`LZd_eN*lc-DP`^%h2f^l^{% zbhR>q(>`|0R5a6x#omcPVFSL;wFWY_oL|$i!2#FtD+}$4p=i_hR18!HAZ3Oy)g#yy zA2Rm?{XshO=p|}SyNMTKFTW{`e%Wr;VM=c%%CEnj+g{{od^}`d&jCiu-BWTl%R#?q zb#wpC>#Q|^lz$wCEKiI?W8>oGuLKRp@eUdiui_@bHNh%D@Z=+;r^)UeO_f4t05t(4 z6E59Q`)u}*)b6?^!cQCBgFGv_4p7Ymshi9yt_sWvL2)PjkFEv4f07CUUzC1{c(|0U zxvc>IfOGUu+0f=beL(r5+e(?_v*0@&T1J+ldronplWyChqsdr2xZ-@r$|65uzUI(7 z+IDuVneIjfnf6#&ayIN*fB#dcUv3!(BNh`$>fW|DufugIU?_56jWy#F61<~Y<0+JE zF*}9PK-aDgF;S@Ac+*+-aD_E!N-;O6$>ZV|w1zP$Rx5BuZ(VC+C&Gt^Y5O86r7_xq z;w|Y-eRj1a-r57n1eiRoZKO2RqQN& zHD(N1l>eL3^{*tEuc0@e6T*-KvfTcGq6d&7kd4{@U7;0y+{$&{QU#qaOl1AqAFzcA z!P9L3>BH&;~C4Q1>5RI$~Xo}T{}JQ=PHBFA|AQLgeBaw znW1n5qjFVg)DxzWA~987d`qT zH$|CvuCzf(PAu(p9I6jwwJ(BinOCI6oo8QT)@y&rkCe;mpVHArq;4&oH;-diw*F+)ZMZ$|fY6_8BC?UOEb1bZ*I^JM(PepH$v84nTGty45m}C|3Jy)n zHjxNTh8IGk#x_Vf@4O-0AY^{1?U^U6=YxKRB)R=Wjd19w!o(t-zyQLIvnr_vmuKY(+&VeEhuYM1Bx=)>NMHg)^CJ z`9gbq<#zVY3fT1e;O|cUG^dQos#BV?B+Nn1xcR>p2#q0#?zPk>a^^x95^0^yvapnx zHukrrnIAmrKR!ea*01grCkTy~0h5^eIrZDt#VHr?aKqNo_9|4UR;STYO8Nc(BxuC( zXStw!Jay*SxT4^?|B}sXsFdxN>;Y=;-{kwONk4=^J=n*6Zf1xKnGGeK)wHZ?`jgGC z%TJ<|PTQWvN5nn!2PJ!M-ar=ew$s^?kj{2zFgsm1TbpkwA^;Bq^3Q&+Z!!MYbOsd!fgOJJ9`>O8LrZR#%5m9Dl{3UxZU&KdgyKd?NU0019oz zi>@OrwTY?K;WKet^dl`x3SX~lf+bT~siA+-H^S7>?NYr+Pd*T{*3GV7I6^cY(2rp^ zxHTjVWL*W$XB5)4=LK%I*IT`ds|e%{2S4QlOV4WR7!*XNA9@PsK~hvQmC{F<%`0jp_V5Op$yR%af}?{~_q^6eDt#nldmfB02L`)q_pM&$YSWfB z6ozvO*DjD+oX!c67pLCUzE%FVsg2FU*r!4sUyHL&h;(_);XXFuN*_01g#esa7&;C)hyRGcSkebpQJD z(0ppHHR0t}-*|wU=4TqTAaPl4Utfol7}5j(xC;t0%CxQa5a!;txYjbx+k7-TR3*be znB;zy3+N;@xDR?0gSEM<=m)UpKC&ckZCub2ynH4kuzeH)n_faXGCIJHwoY3G`S^rf z>h69d8~9HfH%Tt$b523Xk^REnxhri+NnXFBhgxSCy3C`fxh;9VpC7Q5mh2hAam1!b zWCTY-b6p}k-=bbolve5t+HF=NUMrY)X&Sn}e;&c|K(GSk3tH8c*nJR@E>J9_c(4VR ze)D^PcX*07I58S$mnh9hnA;p=`%-K2p1OG<43x3z?EIGRVs=K2^%e|%!enQdaNo#= z@k7LqfT@U-Np#W%xnc8J5T|VGV6~Ggt&q>7_p;(+bI8N3+Q7*)imzH>;KNB2`H6Fn za9vT8rublDM$HpP6f(ynjByrzR~OMn^L%@F=>v?39Em=3K8PMExD~MGKOU8IcXgeb z^&PxyUXZ0d!>!C47T&H55>@}W{jNyBk*8q%?{e?HY<6TP0KLD+zETOmtOq#fN`~$> z6)E5>4F}Una3%$;mAZnJigXPvsRiewTAcYT@pz~C0Kui?T>F)vNI3zice@Du16gc*`b zdojBFOBPj>Grz6KU*MPg6s5@5vcN8zKSZL~Kt56N!Nd99EWqkbkcJyHoCHZ2=rVy^ zRb+k|?M?b#86gg)rOzBnfM=8%iZQ~6ij{x(5GRoIW0qKDK943adiE2nmR^V0Z!AoW znQ{sz1u0pOs2{^n8L@3=oEgp}oxH~<|2Iyjo5>E7$bSV-)lXb12pI~^nDh;;$jwu9 z!Ch91#d0UCBCpqbzs$R`XUqOh51>ls5DaljEyZ#Y%?$#T_(aw8-Y%yJGGPPgB~ zwBbc#gn`0{Xi+mXvZwH8aw>dt(v3azMZ&)w&xyM9RdVLa@muDH5Kb4Do+9S>j!B#b z0BdU0GivYw#$|}plh;8B5?>sY)?{kF!Q~gUMJ|yMA60jo3!`xTU{Aj!vBoCq?DY?0s#%w(2274d=#T_%ljsFd*nzL?N z>o957K29ZZJ@;47SWxY3D4|l8kIfym`>k5S(*{=iOZiopqQ!iZv|;t4#1sH5FX)z) z&ykm)Oalp+_rM_=CR~1865J?EuX5<(S3?}KEEQG4fZJfT`d9-;SRw6Z+PftC;fvL! zx#+bOHHO$Pl-5hYGLzR_XiGhjE-p}QrFKSu%5!&*Zn>U1(XK&TIH_ZChH+cb2;bI` zVkS(Fk7Ew{DR8tR(G~EkhUqNVfAG?YZhRSeuHo{OE^0CDu+DZekA%Imh=TA9eo>Vw3e{#6`Pf>=6(+mr4j*C4& zYdPE6-g36WU(=#M)7=+b1IvEOyr1yX0XJ;8+>_KZ`#Y~K?W{jBzVxV-kSlN(CrOt` z3#&h?<7V3_zp`M(3F|(IUB1zrt9gemzgBQ<;0}t$1s_1G%6CLIT%c&5`@JSZ;jw5_ zpL>Iypv4_xe}wnbzJ6pD#Km#}hCZnBfNiTeRwyH!CB2XjchUM%{emDm4P&79< z#Td)FtioTdoy{XC_jgSx*fp61V@0eDPV-{U(lvb$OY#tpJEWMA_rE$XVmy=MRt{l^ z$nn&9xLl5x>fk_{fssl)WE?m^6vH(RBP#j5H!P`CC{!gwnnx{L_h|F z|HJpAN|p_dHK+4<`;wQ6$X|2#f8O@CWGZe{y9 z@47+AA}$6OG~i{yew+@G7XOLGRTDZe-hq9$-VSBwVPX=dpc(0Xw zncmJ|nBYW4g@@hINv$<;sP6vqbZtBIO0dH;FSp3iB}b{lg4gjd?|uOPXt4}!<3lTz z05YU^u%4^8Is4Z(txJjh+fXD%$K?T_m0{t0s3tEf4y!{7NZAsr+>t{+Gaq{@HqcmY zb?8c^ZDhvgMpNH-y`yLxKLG1FbQ(j%hUowm{OBwrItJgBh#IQZL<&i~`z|_VE4a4= zCmiSg?VX4Spt?J#+};RczeZp;fu&pUT~RCS-TgwYU1-Wd3S7rLoJ;-cT zMy>){iPLK%ZL^m`c@QMfYaaE@u%(_gM&gK>98D(5YTpQZQ2fx>g-zy+#oxJe_cP>o zT~gSBAtHK{H3rxqW>H466o6x}VK18T69Y%PSSzpPmr>y{OQ!0%Scw?cH^e03X4YTq zk5kLA;kpXD+&;#aZ-U~X-+Dt0ngg&M{V<)H?}PqSXOnR@0z;W98*Q`Yh;i~c%~EcK z_f*q`yiq0AToL@5Kd*8!wmSU&#+$L({gbpXbWm(=bVPuRvR)%fAb!8Mq*GniK{FVB z=8ZUL5O*9^)6b-AdPw8h+Y)COH_0H}@~lPuil%+r%P^`!tQ?+~>?D=)lyE+Tg^4QLgBdk<}{rXZjLt z^YcQGc(AnT^f&vhI))sQ-1H$0>u`QW;RD2?79SX_F@z4*--s}b=A}QZh!!!k*W`Jy zUTX{p^ts{GVv%ms1tsw!?+`|(=z~zsz43aMC;z4D6C^^9Pmhx;=a(?r{oFl!D)Fd9 zgK+dlJ~>VnW2Y@)F)%Hda_IQL?r3~|kfv7U^Tr z2`*ujTF;ogqnJ|l(yup5%_vdCgn8p0g;!iZijWj<%A7JyMNVj=@+nD5Wici>$zDQ^ z#J0zPd+w2TRsh_1-eU87DX=1Z9tEMuzGn>0PPu(LXD8FoWr5?5DqdoeF+iFCuBkWKd|X1W?D3_G&zx!Y=FaB_G|q~6R+Y61gt z8*~jUZKBU|Dckh0*bhT(DHUJIGl$)cQOu<>al;*_uz?hbhC4@ z{xZ=Jgui%Q{TlbHE_9C9oJAaoZaEvjl;RP+NUvF1dv_h)4$ZbWd53_>ob#t?3UFV!EKMZ>Y{QF%m3KzbuRfwBd(H2D!qAWz(;pha%I_Wt#1ZXFA(peX&h27m-`O3a zI&y&58ThL|f9hfF=Vh$XGnsduJ50~2&*WUSG|&|dV#IoJjoU8Yq6_}^dm_R$jP(BdhQa#sJyG5#`gB+i@4et_Y|5$_tpnFye(QkC{O zcJ(?Z_>!vv;2)o2ANENf8n6GFiXD6(rnc&5>GFO+fdC#}1(GXF4uN!75!4g5=`8T1K!MCh5<^#w0nQ<02d z9?P-c@?tp6`{T&R5WMr0zxs+}L`m2OnA4ZqYM5kjJ4m4^B*+0~4)PJ*u zf|KPrmK}Jr(qr$9n#mAgVG*!;R;(Ogu2$ z1JoBaO&D^7dke|T6L8`lXOqRUFUb>@%mhf7U@wibA3XTD%vduLz))n#v2i*BDV){C zZ4)kq#z=!@=8S(J&}U7uE?VUAuCh4}-hOIwVO;5Wpk1?;)RNpy`y>TCExbkKW73?P zu2pdD78Gj1W;l+mjO>l9Vo+BQs%b}YWv91w*eNVc?O#WsaukvkWP6^Fmr@R!N73r> z4cTmPU9Wp?{ux+c)@CZv;B1T|oP${}jy01>NNrLw#~fFgb#0Gk(%rA9upUb_lU%vv zz2j=f-Ig_Mb{qIMK2q$%?&%LzI~Z6jr?jL?;P$%0<1CpYqE}ID_Soq+?|mB=?%;^V zNpz01qCGUi9L>C04y%|BGezk#)Q_Q%ew64SFmc1EZy|W`z)*#^oa*|4v=eFbZNZy# zYTaOa(?WJnO=lUJbSC#2qI)88^U7o8Za@^*1@iIDra#T`!%fqXVo3@s-ukn7aobo)8Rja>Yiv zT6Yl|zEmP-P?gbDqCIkOk;rvyiXVP%kT%Qp-#EirDcsUAEpT-Up}3Uaj^E9ayW)X7qf9a6F%$YjdB z!HkB*Zv~E0+vFJB~26QIr z_!AQxS}Q{Ls56qiC|Q={DpG^f(b>)1Wp`CeDM4(Dg>d{t1{9eJlCs&+uQgVzDkN*fh8^a&zLR~ zrWEUsAd+=Kk|DzEh`ZdXgeOek$Buwl{=)9-PX?wLX}ppRHpswM5dbBG|(cAljxXKL5e<;GX{hFACg91w@67dG9~vBW_l0RY-$k0g&uGDE*kY~{!uM69 zww)(Q{@zU~Yc^AQd02bY-2n8DSyL{)dyJLvt}jaIG!&=BQiX?hhza|%rje=x6i8Emf)unqj<&z!N^GbC7I!ScD zsrKu4O_?c%^4`;^Bw!&p-a_jn{r%ErFw+T1ku=IY*H2@&_bsgrI1cH6T{wUev;jP) zPh>V?wz>S|Lj?8jbXiRQk$;1G=!vld*UaCwYrb7*loTTAT{1v^Y}OVp@T+s^D*e!*b!NaaGg1l!-%8it2{+Q}i*0 zYKlsN7zLuj!Pqsh5v3b$vH2cc9O9Gu6xUwB~?mvGP3qh!nF zn`bWMeE&#ZaQytpQveTY=#&(RI7gLV5hrBMeD88?uuP>P5@q1X)iF}A>+g6JwGsZ9 z6(aM;b;6BBlpd3vgFMi&wa)X}ZHz7&-l24VL39KmhS#sBG4u4fLQzNHgBsJyf zslWEhcF@gs^JlRN9q>_I^Mdt2k550E?Fj9jLvF$4lU&j@3q(G-X9wNIa=S?@L@K*L zV%~=NuLy@K&P15=nA<*Kv+NB$DKO?pMB+n=6F@M^t{z+XYGv||_z(teH~#DSCBhiK zMIg525NkHte9{5-1^rekh(x2y#x`K(Z|uc*AwJiuWK;v6%*n>H1yD*ko4wB&Hj@@p zq8(u~X@&4auDU}E%q?Xh2~9_{E>nqSCsDIosyF!8@^>}JGjNLj)Gb&m_k0e~v@bhg z{6Ir#c&=?CyBQxtr9&f4mPyW_ZA9r^BU6)BEVX`BsH~t)t)Dz=DCI_yP)IGNf*^s| zK` z3XNlmR_$CRS1ulUZHRr+BH2s%PR)dAAW{03`(!)bWi_KNPLt9SD$-CzDg7i1S{zfM zxD{592#a)+W9_Lx&!m}(<^7q$^YHKwwSDN@Fn-+UzHAb2W!$)DjO|#{)x6_q2t7(R z+HSz~yZu=c6|nn2!I5_CO6u0v8vU3Fc^Nx4lIE$I=wdFiT)9auwJ#^K!?CGZ1j{); z#yx)8@65oAP~_`xban~JBRT3yR?$qNg3U`XDQBG)$&AYhJ|5Dk*|?|2nhOd_*5S23 z>$q)=3)?JqBc6H>GSXbkUwTlM$F2RfKUkF+xTiXSxngQN-^BemNbr}Uh6pQ7RR(w7 zRog-wD zn`v6iaTFhOP4&-^45L}gv|F?*LaACit(YA$jP48qo%5Vs{XQb=@6x*l>gwZTE=Xd112CuE((Q%4{qgkg}w zs+&O8(iG(}izW6C|BJM949+BKpmdyxZQHhI!igugZBCpwn%K5&+qUhAZM^Zjv$a)Q z^;LbfRlEDI`$zxi+kLyvJ@@o^&anTXk5HU3!^QcLF$X+{>^s%89-8xt{bhdadn}ZN zgRJTsEdyt?Trf0XZM2qh6qjIt^P$LP^BmV5jdwoR*ZB!FP^i)v3pu!@TRCd2LfCTC zlm}&!Lgme7M5uc4u@ME5P=j%r&Yj#FIQ}M3bs)k#tm?t(WvDpLtM^s0Kez)8k}?RO zYl-MNSto+huCF!W>f{a;CoqVq+MpbUC*P|sgMa!xMt#D01nq|vw8*bwwhoQWbRrqX zfFc#^V$JzzcFO>E1w#?GWI!c>dA)AX-Uymcrp(TgQ%90?nFus8MR6lVJIh)2THqyk zeRv=;JLpB5aynHA{(CVY%N0V$v87K>0v@U~(P;%umxgZVsgNj=jrpkMa0>lyt9){^ zj3vh#anv4#pSVvF@t#HvwfC4Ptwive zbpEYibI?a`$dAGXWT)!%?4~dl@ z-Z?O_p-1DpQ!-dGE_sR%;Zauiqs-C>im|ycE*h-S0=A}+@UXQ03=+XZ-_wXqBpL2; zKqmtOK^ckyc*U|-~T#=mTRP8;`MCybxkYqPzh zw@7QSr+LmA=ayiv$X@qj!ppOR$-SQcO$UC&-i1CU{thkAD%(*5EmONBlYFToN>S?) zSC28@A8@p-K;uk8C`%ct^$=q z^W7v~XBKZiLfPDUbn~rov2s~2Cdonc-Ppb@J_}yf?f1Z~SS?k2w-P%M&;vwOuzSh^ z4eP2EewQJfZy?oTa&^{>7m`I0#?TeU4yNJC%1e8dm^hiAbEtQ#K*PO~i>mPHjtQ*J z9hPAOg|R@jHr_M(?`8RwTdEG7Ai#3AhgMBCi!}1NlsZ}ielEFv-Po8;TfG5JrSGpy z4m%E%nBzO>b6bdRk!aS5 zbW_>Et_+bJnc9de8z(LoMSbUP!Q^RclmThDi6~Q|U~K4!5BgXNHshyv zJ{bK^Ex?Dsa=8wUj6c-ZQ&T!>;TTj7zOkrbG~0C4MNU;p>tEO(xVsW827pq#qLPf;85oFqu{v_ zew>S9{a70^A4%7)+?>r~?Jv{reMWke3o`K7`R3M4`^lT^A=&oh0~d|4KhHMGRYh* zE|BX`HEN=~mn>EJwf1K@)bdz)(apq>>eq}jJ>SsV4MhD6Vl?nUypdQPo-kDQZrwVlSrmUFE)4_kZUS3+uKb9!F<3{8Q}3xX7QbtC10bG4GcT*R|Le>vIh z5Rrrq0-^q7^dYHH?MF*EemL25WV6=z;wMB@hTiZtnEF{xU~wBhmr}WHECSY7gZ+{N z_O5Fat$*XSF`DV2i3w?}H;=|7Gf6`tsns#%wP7ksJTiE9?EGfA?98#Ge;#3adApjJ zz`e>wm_?wrtc)FcxfQLE?GG=Ya#Lx_;w|aj;r6(C;xC3a za|#@uxHuTBvC~uZ_Ra{7gg=je8Y|{z`qg<`%>CBMm;z{h0_+a7y)?$u=N5cJ#mj|Y z3>e+HP*aq8A91ZdFi+}AjTx~RiU-bZ zuMu!hf8K4?Grkf?jcRU$PcpEzXUjl~^d~pW$fJ5I7GD+^Ci*ohd5^xOLjPt1!d>49 zMXP-(O56E)z$KF4Q$!tTp#~2---BK3a2nP{{6{4yToanCtxLxdRo2)^51OIytOAm8~&r0LkeNIj*?~eMe~W0=;5$GTPCfKC)|P?kp6;O+(JN9A-LLr z9rP-cv}9EAM`jM^sL&85s3}cWH}V@53UBTjkPtHT#ZXt(@1zc^W08eXVtZv{a%7MP zG&D_k)p!YqZFGVy)Cz!CkL{bK~q_~i=g~oe&Vgu*~bUnUf#Cx*moYH-$6G}DxU&Ds&OYUW?y4@jJR6n zGu#GU`<+gg0^to(4%v@|A3s79%a%pR)1$nT{0GwFy{-L@d|KhJh}2ZM`yvKZ7HJe$ z*>!55OzikI+H` z^YRRrctC&4HA5OEf5@2VOD*5aoZ^DY!lhZY>TXc^)OpMsY8r;K`E5iP4w@a&LAUt! z-uS&C=Z)-cDUtqnMddGbEuMgx4zjlq1J8Y(dzwL+ECDkPNu#8czG$9pp#GSgv#y25gntSr5b#g&96WWy2Ojiuf&SXkJ^WI_<}dpSJpmN&(plMJ zw>lo?uWuPm3B7zC|8~C{24eG&^tr<`@!eN*s|UQMS~NFlr?*6h*FRLb^o2Bf>G;Zf zw?F+}1Ps2VSk-cY?yGLn{5)5pSGLvl8N;B}^#k+_Gvh9e-_c!!7;YFI(m})V8Wp`l zHmU%U2c~&DLGvfpn@`%>e?$@e#yOFT4>C_ht<*apaDZjX0{z&c?DfnN(2-x=8AX(60qhImO?}mwcSgqBw z8}^Tx3p=a~o8--0}CECwZ4{d(R_v*)EI2 zf{#S?&X2U^g)uk%Prr|^t#|=vssH^F{GU#~+@*FLFG@fMDD5CK{JXrn;8{08@0%6-^O~#cB2N&oLU?+?uwT(Te0?bUJZ%-!9JL^W?nnuk zXs~E2u6fVj=uolamE6k2b+K=Ur3-HrJcOmM<&kV_BG)ERqU=HOfEPHXbQd~VoS zGW_sK_B9{vu<~K|qyQ4I*R>`Gk9~my|FZKXvg-qr&s9J;)xd4ov>i;@+~;B%?>@qz zy9<`1`Y@w)trLxbY_Hs37xKb8fn#gFh#a}p{sT-^)*X=Pz2X`JWT z;hio_IA4YK^E#1YXN`c6#y3O&g&9;&p+6GCRy2%TyR)2e?H~i5!g=W;~ooxI(> znn$9}5QbWOT`_ijI}H8^n~i2M{9eq%BFsUxRCrK%&}0gjm&)Rl)EzKw+>>#}Qwic*WcR6lGLPx^cf<>s(*D7s|UVxNUI#WUq= z>!1^Gu(A3429YwH4k&0*N>0>$p(&KTRuq#Q>~%lb{85tD z2I2nnBClKl_m^w8oyB!(CU*~jNE_RiIPU>S5jN5jKyXZ3=`iY>c?IW;Eq4EC|0p*a z%|gFQ5&rP1uRLx3=7w=bv3*PVjroMkgr?A&ZJ=_w1ka?2<3z)_L;0dA4cL3;t$TCz z@{$$#it_w%AVSP(cIP2zmO4^-GQtr)af)^K_EIN(r&-Vwf*|JnNx8b4D3(idI{Cz$ zp}+5)XJ>tJxnk;cQK^@Th&{+E1H1HBRfN-^ucxP|(t*!Y_q7s*gTx}~K$J644(mB~|b z_{O>nnP4xoFoQOp;=}6}lr-f+{)FlFhpMrg8ceGg{p`1BLN;SnOI(&hu~ZuCM7%6` zJ!OuEh5Y=GkdVFQ>%zU{@r=FvyX9pvp{x+hGY@NfL2g0J8i;jQXY~@YjEF?&^dK`m z!Q^zs-#wE5lJVcY!@ikQnC1jM36Ga8hXIgiv@U2MU za#)xe)OVi0Q7MS5e^Rlhd)U!xOUV~5kFpUFchJ_h(EF~mn~Wer3%dUqP|ClnrxZ`; z7s(D^EfP!Z-!JblrO(I*sCq>dJ|+b&Km%3wXsM!xZ3@cyOnt2gNB(_U6sKcKMKP40 zl3lC|te*7jEI+8k$lT0+`|`8#AfKqy&>u9ba;PNBtjyNDahsIqo70ezM8}mOsSR`} z={l4tQZ3Yrn^DJC$#>3-wdIuBN?T@^17og&m>0ra~SCASoFEYv@RH9eMvAo<&-` zfR(u?A#;8S{&_QNBEJfd{nefX6>GBInGl@)8{-sORbl#fT%$NU+$lNK!<0CyWW%C^WEcJ;#;ULaDzPBUxc@?5CMjH zDtRuYG_u4Do?VCG2{f`_ou*>rprkIP`(wCTH-Rk|r&)uiH=Eky`+d0LD@d8%r$ynv z)Bm__cAwe`)@L}D0(3ZI2f;+3WN$im6D?WyUbd?R`$Nvo@iZ3jLrezSshry;3$W^7 z|4#bbrWvy^`|`SrsMkJwIVjJ1j1iv+m7BOTeFozx9n7I&TN7uj=jOb}4lHn=X?+{YIa|C3 zn3bZ+?J+$?w8n5Qd^-0sElC*7c&I(qz8``QO3*W^nu}4dgognVVMZtE(}rJa&fPa5Slh>I2`_NFIE|B3FBL3*wG6X)C-+k%2PZZ%e4YDcKFV)hi}(P(y?%&z51}6_C0v-<+pY z2g!8|hJr%cjxCIEmmXOSL9%gZ+Pp%i43B@zv6cBL8DTk-IL>0Z-M4)at|yHMCF>ER zTHN`YiH{4dQMXE0g8WoULC@+FU`V4kxJ)`nn9slFj;~n&4St{}Pg|?o=aN+!D}C!I8O!RZ9+_Oo znjW8$(-bI=$WB#)jvR5D4~zT2I$C9(~W3K@#ooUuj;+p+5B4miX7=mptg5eZw$Z ziel5sgIa2{=pj}Y6gAxn8Y=UQgH@FXxbhMe6jiLaQKAs6-#YQ|&Q3QTbLWHv``6(a z{)7i_mGN$y6Ix5fvqcEWde?YHwAg9OzYJJ!be*j>flSs58*Pqdt2rh%C|4Qg0B-Nw z>nbicW{pe>!pxZh0>JNX8cw4#eAW?f19Zu)eFux)%yW-GGb`AZLs_G5(zWXxv~tzYi#F(m~Pcp!ID&GwHd6`>OT{1 z8|i;*fb~&`ME+wlB`m{x*HwCz1(e1 zs}6^q(N{$$Pr#c!Kn-i(^#LhpT<}%AL(3@`c?rk#$Ar#!K(j{M$NHA9#&?k%o3H z4NTU_t60u3zA+0%9?vO#4~%yT1;24vgE~xxmPkw#C!^AC&dQYO2Ad7wbm)`2ELgc% zHYZ|W209&CtBRad16{fu!!I1Sr44`WxqkStg0-F7k(viC zKV2&+P~OvP8>-r3X7OG?Gb4r7cSblD(*Z>YC{GQm)udhC&<_ZT-gBhI&kV8XU;9c- z28w+G&Yz3@+(ogk@LI5BWW)L!hN%j;ay7n9%NEc4#|RYsWg}#7mJ=HPNH-XTXVUkJR=6@3$q;*w z$tTxj(3d#@U1+~`mJd*Rrl4^h!==^mH6#p^H80R%D-iqi`4U&eq9V3*BWP*UPI~H! zle}aL#3KF0#<@6BuT$RmnDwD%CyTERsm~acCbp5`mxl_Tb`FJQ(j*BS%?6tCV5NR_ z9ii|TMG1;6da!O*=iZ?&bS)c|`#&vaOsc7#j6T#6bb9!e3i7m@Bu455v(gOr+X}Ob zN6`J-a-_{rys8)t>iQs_w-)}6K$%Nig}BM9l5OZf z*%E`RY{rqeIlJ7u9%~9mFn-5vG2G;wv@Q7r4BeeF;s1sHE?U`RSBi!I5T3-Gmp@?d zxf{_nZep_?wNs_{MD&bY!a3;E_)Lku)O0PX{PRN1UMBTI7F`9Oh)q7TK}ogEEri$l zosOA14O6GxD}+mk;G--I>5xjk(5nYWlM(g+H+UAkGbSwtQ!Wj%B$@4JV?oDhn6);i zylc!Hv+~b^22u264a|;jGH}Yfo3`NCo6*p?rilI%4Ql;ni2m95Ku3s4d6a7N=SgTr z$aB@Uw7tdE@CCMrfDSi_OIL5|x=lSf*pE+snQ=oXahygca4o4Vr=qnT1%fq`3p(Sr z9Mg;QUI&a5`mwEoSI5XjOWug>Lrl%qfKE-{e9ui>3>pXVdR{>!xQ@phu*TLq>N06X zB1_2+V|o*5|2v|pBuLdrj#u3iY^!CYHJKg;9&69`pxbzXEM=1z%lgJuv)tKxHOF|t z?)@{Ys0e`qwiZ;QndrZ8T3m;>$uY)!w=to(Ge>%&HTEp zs^~rQ5~adTyyvt*u6_Z~zJu0kOI6ihvYI}z)=GCw{ZSlFuM(580wRSf`$9tg`Nn!3aiU{>_d-K4FF<%@V#eRU-|*}?EVprzhaI0R5A zlmh`>)t&_!Gz5oON$&0pT(t8Baj$|MG(g ziJw6$zH`gouFGXRnPNH~7Hl<($o5XOL@Zi@P$*MX(b&earF6@}j(ujhXF+Xc{nPFD zO7`mz#-GW}_8zH3Dj&XjKcfxPt$eXWk6tb~@PVB=5@c3`iSInl$eb6vyy>Pl)Fmzp zxmihwJ`Mqk$FZ0`@&vl&>!h54J-Pqy#lIZOR$&BX;y#M2$zBB|D5=0WZi7}SLl ze>9kkTQsk8alJHG4`H!j;*5Ri@44LaUK-A!M46354Mv_74f;NjOCUp}3a0={xzHkr zTkr_7uhrIe-%Uh*uF?LP#?H4|>YHI+(U4N8jRqd?kxioztuWcZ?Io7we;n)>o#W?y zNKHLdS=-z!Y#j4v&~$1RybOgiR%v?fwZ0qqi!*FGtz-M{U33e=oD zEr&+b%qOD*Ng}&Epl?rGNqUI!qH3i;z5Y^wkXk9`lyLvvzEz6E+ov(pc6dkn9^(32 zXrUWUyfZq`ieLR(DWLCU->+%(JtgZ|%+kwc*RR*T=J8Aao!%_Yy$q56cu$xQbkXLX z74@V~6;y91%*`FpbWvF>_K_ee^Sp!G045J zl`{rVOAn4I2yIoA9Sz@e62wEQd$3dyX9PCb%=42oc_jc*-<6pt_`oP9B`Vkvy#_rH1c&6r+K}MmH=rQnS3(-gzfHp8JWq$=g=pq$U%}$B zBC?a=c{92Gn0BS$ni>A)_n>?P1q@##GnG!dr`glvg(Vr3XoFwP;Ot*`NqO7e z()o5uiz>QNqGcC+oELzslf!>`20-1a4EIL*?LNnZ?PBle=N+>JEwZ45!rXVfcZ70~ zdFA&_|GV{8zwloKFAq#&F-7qoez;Ly7Jax)9Y{to8nl`#G{G?;K=JKV-U#{6FJ#a4im|hCFy@+rAz5kO^)F=#M@GJ zj)OZVWs%>+|Lf(yhkgy&q83qNc|-O6gKy=IFIi{>;TwTmn(m6owdiAAnrH=`Ee{gM znHzSc(o<}mvvb7}`W`#q_z3Bh4v^_B5Lu9vPT7zJ{F^?Vn3NJf*_5+5#bx5zi!3N3 zO%o%E%NOLzl`|-&6S1W$i=LFLn^gE|iBjz^irNTE%_693#xWJO5bn9&mAyOi=dly>s7OMR4-3M(avIwc_7bjw*qI>+^g zX$6h==}UU)J4c0ORuvsqiuV#L6|43X!Ac}HCw4(b{LH$cv>{ha&Ti;-hc;Nk)cK6x zA)&uRq)rh_mveH<@1|_yML1@yowOsWhtppb9xx|QvBxa!$Ym+UthxVaab&Fzu3zqD zRqh>H?;moT99ta-PUB%$J6MHi2|i+@_yQO##1DBWu<~M{neH`%>|%6vyv|uGL)Xs9 zRxo43GCW#k3*aBJu_L$5TTZlG>@xnes9%S-?(w_XZR|`4`7%BGNZAnZ3r6yB$yqP} z#j$KuhTYp}N}$Y`t&UQ^&3=5>u*qRYQPfC;s4$S>GB0M5N&2e&cf^y_`hB7~yd1xO z$=pP~nU|=a3L}oJM^Dv^$Jb3wo#3rPj7eH zhpUKjZAHGXf}wXRUb?7sp7F<}%sh$Pxnd|M{NL@*Dp>=gOq%Ma+4JFccy`#zbq9IO zfK$`gX7DITk=#c~nNw6N(lLfAS<~hVeZ$mC8~a(t;|MD;zY^X4?C0Zxd91|qrM>^U zhX~LPgynXnGG*?^i0guyLo%d`ONAr8uOk}E1$RSbC;7`nitz1`)RZh(|NECH>;9mE z3^wE?c*CE+WU?vXkKlpnYN&Bo=)^Usa%0xg(JJ|1@01NOeUo6Y;K$&^<8=_MdSnE& zA;JxCdBi`FhQWTe$lxOH#fi7bqDqV@z!`rdgbehFfn0~hm4h> zP;rjy6M*`);US8Q7R7h??K^oNOdkfG7)j36A#Wd^r~+8d{UK#Q|DUV^T()s52t{y4 zFkY$gUGN!5J~37iQVX~dS-~l`nfM3vE{Hg}u~2l~Ux{olq2j`1)^Cq&hHHaAzuAB( z!?nw?eW4@%#tG1+sr$ykLYga`rrJk?{^|h74)>}ZI1dF${))^>i#`Q23f5j+l79&6 zF9M!-M`A4ounnby9#KJ5t;7ENqwf;+5vq}riw?II#y!d`t-??r+z$K!f=d+$Ybi#m zBfCQkiwlN}#Fp-l11`qh_Kh0$7knCeS^2)WoCY|2IDRU^lAUP1$w(hOX1f*`MM=gV zL*XuBLyA6nFi3F3mIJVyzARir`d{frWy58%A?5QL1B7Jald%J25JZIG%+Ujav@rDf z@Dw)>tg!mut&R%{SoUhtLN{il9(oIoP`J`E9RjLp={l4C@;?`KzH^YPE$d^qq%E>av z6%P%H;vuM#ltnhs3SDT<6`z_ou0)Y=%jF-H@V|F1eBVGSbVJ!ld@krdGigFWD(L6@ z6Jkt>Qi|5}r{fe;TV~RdFI%Q`{>&9d@VG?FSOxQ_TA zOa?X4y)&p9F}bs%4a*s$iyINS6U-WvY&j>5O*FZ^L!!+N);!G3`504=*bp-N?zO-h z8^WvN)-}-@Ibbt~s5xjD%&De^OX`%>M<&))xufMRI5eTXQ-ns%8?>qt)auu5$-I-9 zjQx!K%p%v(TauVeCfDIx5~_`B>z8ejbVgSik!&d{%`-KTHm6$Zs;g4E`&;U-Y+=0< zyNBH>ctl%5ugu;xi8g1E>w>Cw80Pm~TxQ5=Bd7F+L&?i{ey zocA^N~SbOxkS<3mm1T{^^Jf~5)0s$iQE1j`T-`hm?VcHY1X?@hh z5~eWX7|Y14TFCWXXvWEV;9_yw#gyb3V*AXdeY(D#pc#{|+)`5w{0bMPxGBUCj?Z;= z*m<5fDeDF%qt2^)NQJ=N2w?fBB=+vhLPskFRMHpV7?9;wSNnlv{dTDS%FZv7t}qDd z>fRp}_82+b)J1t%`~0XFIWz-&laPLSW4N|BY(~--J-+(fEnB~R7HD2!W5M%i8}OdN zcGP!WjU1aZoFAdxamBc%`uG?<;tPEy__y%DLELAPfSUR2;UUQb{(K~Nf4lnzgcFW% zw_0Q9xSbM+a(5^{&SdbZy{^#t_rEP`Fl?s*4jEnYM94i`XWjhhQG{nEFK5I&~*C#k&kxeKz zdY}r_$6>K-C;yf=@Soami1l-{^7~wO`E6Ctrge5FnLGS}*l_y1t@btNOwqBb8?Ta7 z?#F&HB*J_tzOv-TMDa-BlKwOPdcFUCjwO=7=^^JONt8mcZZPdpRnrW zOXT7xd2Kv^dS&XXQd04ShDCeR3a#A4&>5e^_*;P1`;PC<>2;INo{*>~EZZ+}c>1(3 zG_)+Zks!o<@UQZlevRiVp=yyv3!jZZY>aSC=Jz{Pph*`6P+h$AY2taA;2d$(Ba{Yn zo|#(T1Fss9XB}(!1nDa#?O;+$_XwQ_cbh@tn{2u1MTyx}^b&%vq5mlh%ohBi9`n_D zr+u)KQ3HCSNeq!~^^TGmD!2^r6(`7}36Qf%peEp7v0P|fsMPElYt51)$@T(%blajA zdfs|yhC8H0xNDq6?L)gkX^L~G$fkNfO|H2u*j4$S;PBa!5d_P`MIogP&%x1(wL$>P z`8NkysdaLjKyK;Y3h>nBlD?nTQZ;faOeKmhY#uP02w>&(4IXVi0y0RoUJCx|oe!KO z8FV5N=sBu}3|-NZ#2q3dbiuUfgYFNBVII#gEK_#FF|Q#hQuHaw>ocoTjfuFPvS=A8 zQ{YqXeE;PuZzHs?CM0R&MLVjhT5WrDlP?QPYT-aUAvUkKV>w3SC{mV5i%E1k{Z7y> z&BJ;yHcCRo|F-iUs{H;m`O~g@8kmEvqU6%!l5cF#W3h!LgwocJMQn3eFT@wt7v^LV zQF>4@DuH@%f#2~;9aYo&xVK|+lUq3%7Bejqso@z;D}PUa)YvhIgGl2ERFV;WUK9LK zO^VGZ@=aio(DF9$0qIcGqS8RtzBrWWw*&jUH1>QTff~Hk5xmqskNfj9Z=rY+bRxID zBp`BctrDXoyCVXZsC}hj&YMfaozgQyRNq&pUJ}pH{t1qn=FRA>5u~!N0Cy}QO^4$& z{bSas5qS@-B-Xv(=HDzrN*+uB!8hxl%{m%;t(<|tUqsC3n%ZA$QSrf>$OJF{^FapY zcxSb;aT1IVkG|gZ!z;S=GDp%v_r?)8Q*nQUFp^`DAi^pEeEjd3L|9mU*+)FEBezLQ z#HgYVpM-4&`7s}yt%wm&Rs{W=m1NL94<);zj!iQ7G4V4Us3A^nFk1K`s`aQcAmQNI zf-@z+w-4z<~FAIeq=jBjezT?qzmYcd|ee%XQZh z%b3BEyV=ugf6Y~Ub1Vs<#q72eA#K?Vi!S6j!95s>Cb?_tJ)PM^-Xl`T)m8GH`=#QK zw)+`>)1sCbY0EJ&+8K4kaWqa)TD@`DYjxF89a0gZyQ}(;BDASqQ|&t)2CJ3#aY^Z& zEEYR+_V;V1_3TEovxGz)lX#$BySsj02#%q@iw9!2UUPX9a);y=zzVUOt_jyxhn^O$ z*8OLC7)V`pE`;b{?1;(GpNX_%cS{_^gU1_+wOTZf`aQPH-G5iV2<-IL`_`{!F6Z3t zyrw;p$>mV^*5GjU?Bwq3>3y)MY_}F6+l7XOpO}9ahlSv=Hx<}hICqBnlIdg+63}$3 z|Iz807t=eDcnKp^-4)5K)2+ zN^(6Lv{Vk_zTQu));I7ot0tS%r~eZJoDzXUS=ie!xC4cW=BW6se~6r()gF8ZAZ)`1 zfFRF=wKV^W0mH`n|8Bsr^YF0!XKtyg%iRZa8OS4imbv4-`Ka$^o?we9JAoMHpJXde zxdt?l;&Q_ zj+n^Sq=jnY5TU1VeM1Ud)#Iv(NXEXQH^dbYXxDgD_-(zu{6mC8?)LK#Fo>zbwSQf6 zM*dcLSdlGC40VI#9dSxCo-9(_=x|)nIT(uOZGk)TWnIeeQc-Qq>3NhY8u6F8c~N(5 z<%SxFfJ;qlW$o^eYr!;_@Qg%ua}`BWJ;AC{QMnse82W*QN_52$X_IV3GyB&Z-Zy7FH+R0ll{!=rF{ahz|Xt z3|64W+5Hk%<$i%x4?{5A`+kMMP0;}7KGP7LVYhR`;k&jfVOfp;($*5chV9egj^d3S@V-;h9k`!=9D z@+dt2EkmY8>kvS@D19A@R-GwWpV;avS8Ha6{%Rnw_=7oFkb`LxRN4)HUo3s@8t2aM zxg(vk;MSB_+AT-rx$)Qc-2voPE%3HO>D*z~o&ZMyvLU;%B0#ESwhOoRmEW{Nuf*)X zZ7E9ZT9o$PAYQalqH<7O$V9%7W+@j6UrRH3N)}E(ygE=-R+e21gMRxoy|0>$+}^)h zr=0AuYEFp>uy4*=jogvyX-&-79)cm_(2k6mi~?ywOsH0-`l^#ydS9-DHS2tylG+tJ z(C8FrTTxTlEk3E=c!3ssnQbUTzbsOGA0BsG=69a7AFeAUuBPr=qH7qh1~fn25iN61 zH5R)*8GtiCSjv};v~Gp2ntH5S)ki@3Dl}Z3EKw*U?X%hzO=gKz#LphPGj-Y`!}#4j zps2L*siqAHsqWQ^Rg>k*hZujEor3Mf>f}4nXqfTQ=Wh3$XaDAT`Z?${%WRZ%*Ti-d zjiFmTQlMH`cTcZXXb8~CMeMtS1*&z3`rP#~xdh!Jz2J6VG@9#BHA}{KS{)WN(_mB& zY9E0NxLBw=5;ZHSxoyU~2fYRoykY4W!VZ6qv;PK3RfDV+E#~19)EQ0FpzxO&@x~aN z_j|G}RgV*tsz@o8e~uV)9vIh{ZG>g7KUe$^i5=A`OpCI_!izOWHyY9AQa$!sy8Uy~KUUNw>PG?_UUnP(@1WGb}uR8cAvdkA~aLmwSUK8?< zm_@X&pIayVIl=={rJ$yWIcJfxvhl@p;GpM$sP#u;@zmJ8EO^#)cb<9az;`m0g%)jms z?jvs_fwB*icMQ*!_mxkbL;ot>WP0lXt1onb#Lte8lGo{{&hZ{EbuZ z$%p=(_v8&^ui|IV{rk=hPVXRq=Hu%b_|W<)^-l9v`hN13`l9i^`f6~_@)CPXaw5`i z@RYm1dnK|Bk^~KZeSS@TklY%a^v?T5f*QYA-h0n_xBW^%_Mq;s_fM2p5}*h{AJiWx zacD{yQz%SmRhT6xL^w-$Tw+#gLmz)aR=PZjJQ_p$J|=K?m@S;!Uwwn%vCx88x1xP5 z{_c=&P(EmNG=EF|cOhb6vfz11aB*>oadFb{Em0WZs}QT;2+`Ltc?BKi{=R(Yb5u68 zFf{m^)h7`k3y}&_gQ$z~V)-|v&jQi_*@wf?`|nKOc7Qh|5SAGJAAOxW3=SSH0$v7j z;@boQJ(4pNUl20_dXOYcGn5`d5p*-GJW>W4C(G$^oKcO4=D-fpCfc*aT25W=002P%-;Ms#$HUOW!$a4@x=pBywu`-s z+UKW-%FFF7+up(8(XI4e_MY#a%K%O=3!DLd54(^2OW~f*KrWIW-^cXr)tSXcR8qUW8?28*>4TvBFS6*d~R#cvb8g z;hpJFOBj$`IOc_Ye>2P%4VEHCA}i*FhMkt3oL!imiJhi_w}HNa`#xdpc#MH!R8k+K zTwEdMG9n9`kLNyRtdl}Rye4J~l@Ik*?oc+~LA;0LRr;`I?1tPg=0oUyc8o(QUI|X= zOsQRoN@-c?w^FJkoDxOBh=hEYa$$-1Zz=iM4mN8iRllW%GT4F@3A+d{^7Gd+jl!Ln zH`epUvf4sG7(eQh)Y5oaza{8&?lkT6@U-eQ@buo2`K{nIxpUc!#3ouR>4k-&WNDiOV)>1PN85!-X$NXM#f|hP0V{`vuOcz&(Zm^Q zj&ZVarSb4_ym8O*;_(<$i+i(iZGv##h&S5xO6AXmodUR&;!H!*ptN&2*_noTa+y?A%8g zm{exYG8z+2N$qqz#alVfiW8r7HY(gDf;soP6AW|?#XfQORueTzLUbZUmx_F8&Xh;u z6X{7002}PYX*WOGf1sDx)R(+5Bv3^4UpVzUNCz zR^^Qxy*W&es zg2jXd_Qm_fiG{VMx2DO(kdkN_mtuLj#l;%gPBJ_5jgKasg=@J^maF`x&_!ZdZ~Cj? zCOfN}lB=KZO<0IkNKlAbh-*7XKS@7bKT(*no6gtcE$#8{%=xY8 zaptk-k?$;WA+?A_-XOh)`g8t~>1?*7H|xv%?fEhLtaA}qa-%4c1Q7hRg-Jw9KueBK zi;s{0*H61Q=4h^)LS`N{WjWr)EjDR6o0h>wVWK}WjpuH(8$_Io;cgZ+sO71F*TpAVIh-lZZ2i+ zaC|uxoZf1-lig14^7}YsDqzZj-C)9p;^A{jk=@-4koxL!e3R~Ho-_Vv3T+`_PGwqb zab%uss%Eilrk6ow8a;-e%0(tSosqDd%_Vd(QZ=mgsWsU^Jf@x6Om`7pb<(Im?ImzA zST)48#@v~8^(WD`|qcRNvt z!TZN^^}4$m%dCF#=g$^__p?i!MuS-Z%lpA4OJnc!PO2~KyXN!RrQhX`=WpI!Len`W zEG-)AHdm=@nO7SBn1r?U4A0}w%Xn z_1;#Hv52jR5lCQ^Wi$mNJ25FSJuz1$W$<|EL^p?n(?T_d!NNEu$3<@jiI2nO_+%@= z#bU;n59LTO>p^oyg^%UXcG8o_LTUzw&)XR=@yc{!Ia8kX&>qmf*Y4C_-u}E*@K4}n zY>~Cgw-36E9>&ZjyU-lD9X}t4xPp+r7vpad* z{jT%34%#gq(z@ch%DRTSqPn`e76heoIBpsQ*&IyuWp|oAwe`Jsmb&mfAMWjEIw@{; zx?mqxPV8p9*&S?lY&>rceUpHmJ3O8u$DbMQlsC0qF0bIPMz8g+bg%2L!LL}aK3~JH z(XSeZu`|8=1`|9F0{7kz7AGuIy-c9%53JY92cAQeLy<&~@)yDD&52(^F9WFaBlp2? z7Q_LP>nSB|BW)nfC+#L}%`3|5$gBCg0FiGf-rp7o2W{P-6nGtY2F-)b$b8D8seb#t zzavl{S`kyw;MTf-6Pg6uNB#D9KMFJ~{1+{+7OUo|0j@T#N}6t(n&vM}{V^dERr6-}}CIt#7TpcK`d=)ze)w-Br7~ zYpUqgqG;c_<0>*{>bt4WoJiihT{CWKwl9@wO+r-|)v&7cKIc(pTBHcn(aU?#mByo$z zOl~l3m?lY%U;a*RKbeU^SFNGR++rj%QChw^Sy2DnWh9GcMcyOzm}ObNp=VcRjg*a%jZJycoUV^$Za~L10h0j|`8Umswyk`9NkNwL5KSTSHJoUBgmCa>H@Mw}z+>-N)MvgAI(MQfY>U zv?&=DBo85q5IbN=#Q4ch=`92!Og&U`3SMJrky%)v9*sOhAwPaY|VjB3pAZiEKiZNp}eza_K zU^Hg5a}+EmUEFxyAXo2VZXv%1O3}0M-J2UFNV#Betm!N|UmrzcT-0``@oR9g-Lp+` z)N-g@)otr=aol?v6;Bze{8qVLp;mdUDXE#F$)zb?ky#P09b2BMQmmy|epr)f*k zn0ZJsuQ=adIiwL+n_5Yy>8W+2IaO|?(FOFexf(s>nvc_REDvbD+dJf`Y|%cgS~u)! z@d>;tINX`HB8j0Iz}k~>H|KjpyoWx?J}|S3{}X?wb+CY+pVI#S$iWl%hGul3;VPd!5qt2Q72y2IgZ>)nId@ z`ZB?>;I-v7`nA!usE1HThJWJPX!l@uf51S%WI+GZ@Y5)%$+PK{GpqsryRl-YWdjQB zzF(`~4X8X{@nm*nCh;a6ZThq=uZq1)Vd>!TswH!!7tLwPiPhQB>C`pPsiXC@HLq=> z?PD9qs<&`FM(soubLDa7!c2ju=hc;)C+F7-hJL*gcaXNWHjme7)}T*H!A^U7M-!=f zS9h1K%c+JYPjwX91e(yUsD<*3HFCF}ou$@jIL^VM3QGpL5B%gyRKt$%c+NmnJd|JsTT&fLz{EO3zQDK%U!@IUM z>G`Xh3DvvI#}g`hCB}>i_>5B7j`!aEha`!QD$+Rrrv=zX^mO;$s>-ZSpulELCARi^ z4MU!eJ4@qf6}0^vw$m^}x?_Hmk;rTQ85KIhLkaO5{5Nz}bNzBcgt~E4M>DrRZY`u* zhrhgqglmTm(0+Hq=JDh+qgl(t$8h!Pz)Lm2GTR2FAnMqJrAX=64CHfeUr70_f0-is zKT$)(h?oVe@q_P7oc8GR(gMWI-%1$}@@0$X=XaIyf1Gcw}-c5y~J5 zm`E6GSZX~HrfuQq)+x%Ljq}6^7^?89D5^+XVPz54LDpf`A=crTG3P2}FOHq%3Uw^1}`-2mqr2Pd?y= z$DSjpV1+fitOqj>huoJf$!3K$u8ZJ`_g5+5j8~8)`NI;cT{q0(?_@K2$Db(!O~%aTR|4YgkM4Kl-lHitHtsnN5cd5g>dS`Bcgymi4rndhrCj( z%YTi>*%v~qGmU_f`AHP#-^0Hg;qMOi|17JJ1)X3}&_DITGVunzLaN(@!6WVsf!9&Z zUM*7Mxl%%l^e-)Gx%n~6Pv@S_F`{Vf8zD;OQQ@QP`A+qRw1GR?vZ4-|p-gz$y2EvP z*Gbnq!2ImVtG28U)wT@~j_OA79H}GdVW1+HI5MWzDIXgGQut;sCNX{pytvaRWOUTN zU<%&<03*6!|K5fc4oha%X9^Op&4{*-kkiB9lbk+bqbqz1mgQx8jYPZEOHKS&c#nYo z7yDXybn?@hr{v1R%~SDbuEVukS)<<%aw2r|{$M-acr>JjEfH>F4>V#7Hx&$|!z~dZ z;<5<%E2n%?^tt|EAKw1~_UDGc!#jT>M@Jn94(4UUL_*x|6(Pp|@^|oU%PIfeB=nKEZi(IL#Xb?#kgg#tJN+#$+878<=n-A7Ub0d5ee>_mP;$D`vB+lzy_;n;rB@61RSVf9JeOiEc0u9L?*5g~YP`KSQo4^%dq!N@CkLZz(yH$7Y#Pe(v6{<;Gdc!Jf@UqQ99KyYt^>?Z;U`SsO zz|oy;B9LbHhT?eD!C>HR)?;jmA_@)%ArYK?xfU!GinE^L@v26~{G$KYRVv8Ee=p4r z`d*A`_X7D=@Ed5Uck2V+`vv*xsvvI^62`C10>W&D`Av;-L<0ZVe%~Q69b~u>8IpPPc-gJ|SMn%d@dTLx z)~fQ+{Cd1Ls>;!bdYs_GNW6(AOl#4T*K@fd|2HmjE?4H{ADrYQI#A}tBU%8alfEvfb=$Fg=u(=&wcB;1^bsYUeq zqfR$MI|Br1zaW@-m@-5WkjS55T(AmCm>&5YTmc?3h|LgX7W6~zCAbS#L7H`EGkkG% zx)D=bj1y-mmcQjVI*SO_XHZYA!#z3s1v0ltCeG0Nq6#E<$#sy?Ln6w8%RZNd{*eQ( zSS~S6QO-YV9oJV#XLUdXCVE(Tx!y!<;@qx&#%uu7NC1MiN84a7iL6qwpl1fa&{P`jnv7%IS)JaT9EE6yVn)& zzY(>hURS-9NJc_uhr!wyoj#lM@P9+`Uy)^`5r9;1U@TbZmmoI@5q?T?60E;svCu`@ zyMLkoA@M)pfj7wYaAH;eXWz{?$gOa2H91(HQ>QepW~hr~&oB_Io9_lZ#A z%OJo+0r49*}V2eja#1<8zSLtzl0>NevWbh;Ng1Lo@efdm70w6Ye@L^5TmN5|VlUszsUjSF*(AowrV4SD zaQccoiPiT%LpzE1SmXvQQEtj%DTL)O8Se6tWoBe+%<5vEEXKh)Fm_ApgYdBPmQ1kVqeNj(Y#C33+yb07u_`1_cWp880Ms zlL9~vpg1JY#=OEr!;HmL#GJr1BA>zjYfBv&ot!slGw5a10mY*qZ1)VMzn}8T7tHV! z&1WR=5Ow@U3hkL7gD-Bp-kK=7`7h4d`fY@iv&d#pFKnHD8D zrCYqo&qOwZd;2*tW(5^4*d~fF1n+v`zaU{^kdulC{-q(7|7ZDaSpK&H{h!Ntluo_P zdAM3UFHoHt3gh3Ldz~5*qr0^g2}C!-W1%4DPl*)9Pd*1*fR5}gQU)J_gZ$DUn^B^J zKoN3ryp%Tif)D;l%)^(Fid?}|AgKri5vml!YX0duHK$V%n~GuWZAA15UnI7QZ+k)E zD>Q3Ss$=eN4u5qE+D7aZw^8A$=Q@klqVYq9>~3%UgN;}zATP<2|Yi>?r1MC z1z1dM|BnkrgtJYw-=DdnjddFTWr5Wj>d3oEg#J4mzI!X^Pl*`dGO;baAaSNXpWE#L z>bK70EMGqU(YPP(H9eQ>V3xUVwZ>QBTk7sn;eWDb*jgK0cB+booh1P2papq?ZYBVy zha7Y_Wh93h=T{0B;WhwiZO=R!f$?=C`HWSw3V+MEVs%E|8cXj1kB1JV=)fEDkk4n` zwjp)=L4i0XziP=P&M@6Em5^=m0ojvZe=b`tn%|lEG%v_qM%Jy*n}%evtth6S(2jfH zSa!T_Tnk%v_-4mr(wy}t&a0O~u543G2holbPEzY;%Qo;PnLE>tY%3&w&!CRxkj1k~ zWcpuhAkobh;GWa1ru_!nC+37HDDe_qOOS;9*JHA8(c~guQk`I?UZpaH>+uGRlezHa4&UPw|1J-AF!1`TM?-5Y$`wO+1__BrSBGl_WZvOg3qmwp z{dv*$l-+kC7h0l9fVc4BdlS(~(#rjpyzz!CL!TDW7`KYM3ZDn}k|@{tURtEwd7_i9H5Sf zNo-3qCQGv_M{bq}=C>VJLn`=zJ^C5sN6MKBCit|;PBrCV zmL7yao2e^v_AcpOe}pT~pe6p`Huxglp^()iJziQyfDr#72V}DwK$UQ^n<-iY-OatW zVAy%rknw4P@7X{jH)pj++VTq4bg<806qBgAeAkBVG0X0fbps*s zJGO#wT|zPTphThrF571XEcNkZw&DQir^qMSr;#Uthn`;>JAv=Le20roTnkwu!KVG# zC$hmdtX60fgsJY53uje~jZ)^Z9;nR z=ewyvch7ge@_p@CVqDrfPB}*QpcZ(UB{L^yP|3=wj>9&uY=cdr)6U#XYp1)wrXLSo zpWSY+ZZX22^I?q&4-APe1i9K11Ke)N^WVU$rbLJK1;g;y`(zeDN4?tQfIe6_A)o zBZ^&I0A_=}v1xTH<`g5Ok4>yel#(|C)`NM=C0%5z!Si4*D4|V=TQ#RDAc#{lEItKxfp5SV;5e`{SQu($({mZ^CUU2Fr^x^Qk%c4? zT|Q7o8dwBohblu`-Ng9mA8B$DmE^5}jo=M%zMB$1>m!x7xzu&i;~os33VLGb9_BJ_ z#Hfi&D=~%isH#g7G1bthvrA_-Io+tNOG7qg>8OoMdp3pDsIE)1U7G8z0iW_@8p^I% zn+!{;{H|J?0!td>u3Vd3O)AL;M%NFli^Cw7oa5x9z3AQOJ&JRh^Wt-h^F5c))%QFj z6Ak3i=PKUmexC&my46T2;*zCDv`32e*w1ymvsWoQcC~H+-kpB2f}-78x$j#>5}C%L zszx)b#=`AJlXgeW-?kZcD|H+Fj2GBrY17YT*dV_d?sCZ!RLo_WinkhV++98=_O9_O z5>(D*WsQF~8oisf`~7_4ocX-^-2NQ<)}zh1TfAGnTfST0h+%_@HR&|vG%0P2aX01s z@f`j<^j!R$!5h>mWyDyUv^a(_7B@_^E4>$cPV3$Hkbazsw99Q?fW=GNlnMZe}Pmv`1f`$PCc$wTTx^TXGNnupwn?oPuektdZWnRSXl zra;QmP#P=k7j&$tR?$+)(?h2i^oO_-d-TK}l-AdomdFMSeb{aoP3X?xG zJkydT2c}_+MC^Usr8-x=O@Ao$GZ3c8OMXsN9x2`9IM=;(^i~n3%S(Gs5PDPeoBl~I z2)hh{zEAFpsk&GS8;wDv3T4WB8ofwW(-dABBUzP~e%C0C#Ze9K59SFTo)%!n&jtX8bSi2hlV_p>%2S+7{hnc-?wa`gKs<{tK* z+TMpfmts*Hjm%_ANfil;vJVPvVgxk?8DqTPyjM}6! z@(n5#G$3zf6L2L}aTRB9#o1G2N6jswz%>S?2DNVQbL7&%)e4#pDn7|Z#mX5a3fh+M zIZ|{-?JT~2&~8)BC>__vdykSLIjT5nx@WnEx2LtoZ4v3x0j^ywSS?>IUae-*{HdBs zf5UJ?KbC?!Dz_J~2fHV_M`4lDpr>0@rMWtm?s#$B;*#$7uZCn4u$iZB%=7ag=A2bWeXzz@qlN>*W$FI!|g) zzSUi>eJCVW3D68sM`!3^j7aVuB^$-sD|1n}Rp+b8R#9RIq%TdL9VOVSI&b+Mty-;8Gh(zNd$f`ZP_0+WKksuz zd1dPU#V69I+$Y1Q4U*4Yp$KSXC@bXGASp2_K-aF-kS?Q|S3T4`w04i-*CHuxE@J^{ zcIlDS8Wkz2)N0aI*jE5YD+((rN)D+*dFEvg&E2CQHAbaI%Gbj=fHX+8lBT1I@0?M} zamPIL5Y@eeUp}XLQuUyMr{ZGn_7Kj!pk1a**05^5YQ1p1V!eb#)lvI?USLjOzGJRq zzW7k+@WYkSm9TqTyO?45daZE2aG5Z$MoqiYb`EsN@7{G+clV`T)L&z*%t4K(GOpag zU1Y6LxJI}@xLmkcxLUYKxKg-OxYj|_SjAYwSj||=Sk+k5SiPmZw$ic8vBI(3vGTO+ zwBoelH`6Bkry#3l&*1>x5cvYXRxtTRkX1{@uUw$ocAqbyYD|&VtgutvS4^9NV zW!99R1%psuenM~qS4V2m9>80#TPq(IAgNccRhR;>&}-8w&;)4ef%d0$VrRXor7GtS zIZL%_4S|MLXfrG`Eb}b0EQ^FqQq{7y3kZsH;eh@o#-=Su3Iy36$Sv0)M^qg%?e<(VYRKbt_9TEtTZixc$#=XEln*T z&!(5gWz!Al1cC&KfJj5oPs~nm>`Sl9uQRUOu0LNFH_NY7`xpCH`xl+ebkBFsUIR94 zKU#kTe6+c5$^$(@SRt?{+9y0G`PUsDG6GeP1tc?H0Ygn6K|7GwC&2484>^JAoS8{L zplv9G@1*lOZhwYgP5EXK{!&Cp24g|oEsL}w0=nfBMp`Zno$-kwtsH{>@(IZ;ql1q4 zMCDeLLZLq4x#d>S<#xlV8P_X8A!F8Qlq<@dW2`H+E(O*_#!I;_x!MI1{z_N=+QlCr zpPZj_M_198(N`3AG!0E3d2tn#gh#RdbkGa}@4ym~=UE_qNNhN2$l?bXvf@;oW@c zAAcE~vZ>jFBb3X}ca)E`{`CQk0nsnFL{_&%kKyU! z>GbK`Dfo0D?eONu*ro5){pH@>8~@^fo~NLv{HOSCIpgZunZ?7S%d5NoJE}XxM^*o# zZrP2hk0l*fu>R3ctxsW3z^CM=rl**vs;BIy&Th>>(LmKe*+AVu$w19O#f_4lnx2B5 z@}AYk#W%AV4mTF1qY(;w$Pf<1qb9p(KHxKh5Fx}3UVy=1*IymNSDe6)Qe@{fC} ze#+_Ael~g*eO7&z-6(yoI$aE$!T8a0*aJnn+PD(GGkL^#{1Tw?vE;d&Y*G0K-Br(} z`kl>VOn}z2KH1z9^x!JcEv^qgAiM|b69S>AR2`P-Qj7}KI5H1qj11N27jDxS9jeJM zJlHW3R3kFnYB3sA6EZv>Vic&xhPjWWz9!i265L7!t6IM$_%0Qx3P>i{llrV`qd_nq z-v0@0ax<2&XrYWFTdK=B!MUD&pmm^iu64Y1)tZekmbPda6Lkh3fXY$B7EYv1NEMSX z_fHDU|=7^Q^QV+zetD^%Ps!FT%5zLpH0Cmk$pMcw25euV3CMK zs&vM}jYvI~D2B9X@drl%pxXUcFw^Uc)*TRon~swz2MmK078m zSZ1NW%Ias9%c4xfdVTW(dyRTQyav4%ye7TYmjIogI;}g+JMB76I{}@R zb{s}L>ul?s>mSy+*V)&();ZRBnu*Bp$q2~^1Y+W1m1A-SO9!n64+h^2rVX-~wfsu? z1^N|RKlFRy_vDhTpX0-)2kQs(V~zmsYoZ=}q!{DajhN8E(?N=zx?d5_1H1rYjwjBq zM07DpgT{mOJ5A1mytWVasDuYG7lR+ehs+f|&TgQx!B3ELETOX7Tb2=6hG$_}0tqan zve+%F2&@LPURxGsnA2v_TUKOPmShoFmSk91W_fT7jdNX$`!)75aYm1uHV!axjg7lB zeyifF90$yrG|*a|TgK|zE@UV*u6GW1E)km=nHm9%ER7tv(_<}@mhIk@Sfg`AWN4@N zPcTkk?aR0(d#CV0h|Ruo4P`KwjM;J3at~!KrsIs;PDEN}(PuQ2r&p9`wA-YY@Qq~K zDY36i9E~4Mpf}DQf9RMf-$%QAKDT|DX>=UAkLp^&H{Y*Su>R;xd)Z1_Y*U0D_{ z9$7Da(^Y@ElhQWKotV_PfPB(9^UK-O$!#RZ?4=oDE<$kE8eg-!7XH~M2P zvMCK$CA(XrG6i=7V*IuOz5*`wZ}8#{eEFHEF~%p@jbTT#vM2_?Lcrd&;zN8XJbYbX$Uwk>3xo5Ut zW8f$(V44+)W6L<&n^R!fZwiCa_e9yl z^QgUctY2cL@6jE$(PI!okcB6_{A~VQvS&LI=+zHo`t)&vrDhWLy+uIWLyQ!Q%FilBHz;8UXiY;trBm?(XzzJ+ghSUpKT0(g_9P5CyW&xYBdxcyr2Ri;k6Z zSaXcbieEzcrdVg~TNFzlof5!1q$09L9P~|7=F=FbfRoZOtBeU}UrIy%(6~g8HYD!E zdRN6I3Hb)#EEE}W+FPl#MRaZ!yvnLx{TZO&8BL$E9?t$0#}pWLhZsw3?xj8JLQIbX zt%zRyg6%-r`Blx=?Umq z-S*JmxCFM;RZQ>h^yDMi_2Zmz?Tw`o(w@dMi# zqW&|Qn{$f-%?@-OtT-C1b`FapgP1v)u;(AxAz$8BFF{nN8auGhF?R;bzZB@r9bYo- zEI|73GJ&hlb@9ey<(CDPNG^hV{R=hqIg<=QE$- zcn!>#Kl>u--Sm_FCJF^20A%pLFRgSZq!&W6lOXoQP-tATh6qwBvrz!~4c~AEVVS`< z-D$pSiX1@CIWsGUzd(*TIPP4gMpT^=>hTd$gf+k$@kx_JW$uK8x^X2c7uh73`X2_Q;Qz{|VEq1A$MZ3= z*j8ZV5w-e;cwS4zo}gTe2-63m_ex6P`hy^6K9g=I+sVWq|FXv;WTrdD@UvSL&n$dqS{0R(fynOXnJO%S}-QP%#GFOQedbdGm3+O z$Y6-g_4WOG5;DSuVXr}hX}qMTStU{r)qR0ohNgMM+4NJN?A9%~a9Tdj)PzJ@$%GDr zu+eS&9#CaD9gd}J;ToN5XTl@{nsAuaNENo!Xvv5wru%{5BA3zrXhUjTo{4)TQ>GeO zL=J)Hc zl%KzUe%G{dR`?ln@pYmOD+QlP2Cn9+zHGR}1euGYu5{=mVWr=ooDJR8ET_p^`kta9 z&(x5o)-f)}!_M;cxt&coOGuSXSOdBW(Sq3O0l;vVk)BT1Ibnd)v&X(+-e6IU@E9@m zeiWYbpp>F7N{bpB!(e)qb6sVT)jjEwp}*@p13m7{o^6X%8XmPp-J|t{nLJSj7k{7c z59^ZlnxBQml}GfoE1DfpONu`Kz#g7E{Yd+4U!vH0xcv~q(EASuye0$VxDs}Xrrqvw4RSw4wxuNAC90| zILc&(*dJOyomo#qr;^YOjkvvLzL&BRK3F@RL2D<=1Y{xp`|XWSk)czUS)rpj@*%_D zTw+Bb0|T@1#G)iz-?{o$ir?Ph5gM*&9jK*?fZOa2g*YoV8f;$1Y*hwl(}o6!F8pE# z&;&OuQrxJ$+)AKoHwhaC2_&HqT9J=!i`Bs5EQIb;JT`NCKgm?ulerKj$Ke&LV%ncB z?F~p}metPNi$gy$`8V}Bazi;ih0GJOK$s(tV{)b|9306}N2rsottStS?UZtjt;{XQ zi6Xgw`-baNcliw#8GZ4Na#dA>=rq0<15IlC!K~yQAceY3KtA$)f5!^NSp4fV7U2-r zu<7^Xq{U{IG&w^CMP=L~AT38>DeRAM9^mI;-SDQW?@Ll9{o z($OQEZc~OYvlcxwxYxGN=+*G}ygO0V`$&vcer04Vdp_3TYXdByXV3Ts!1l7vXgR@Dn-bfjHr+DT-tb>6Ybi5(?~!Aw?QgvE!gr zSbK+pd-^dmvQnEOP%%A?EM3lH>^fJx1jScMg6k6J=b6GEUQdS}tfxlnU2`tPjM*Vir7uK_X^ms%=uW1BW=dz%_xTO{T+PBrTIwTE}fdDTK& z9W`V2p(mk|mtSH{fKbj8a(%f(yO?}oQaMn|djX7TzcEE!cZ9Xi>(X5B=7$^AQPP*c z;LXWCRpvBOYL|Be>OFHhF1QavbXxtbyq*CCT5JW5R0cIf_8Kw8-d}rgIjr}03M+RB zA;6)!U`mMky8jya)ss2u%|`0N>6)AFmf*t4H9Nr`rF?V)*h7yd#6>H4r7JNt3wn#8 zIPcNciAtc1k^H53aI7#)oXLTtPW7oMBK`nsR!I^_RVe5z>Z(rWUYqGCiJR=oyrhfw zsJnLt1!lOlhzCYmMf1B(EsHdKzyB&*`1-Zbpev|sPEuB@DXG0|uS$UV9kaW!;yWQ( z%jOQ|7VobBWfepkvTkK9&WuiXx56Q>(qD$V;=prXt@z@p=A`aqq>V@62@}~`Rgyk6q=qs1EI4pa5#B)ngV(8;3UU(|+hP&XjD-u-(*5e#tcw)ODi%S;W) z-D|ca8|;;x0tB={G3ToMJ_pQ+%}SubstX&ps9_J+UvQ^w3&sjn+5(1v+ZoGksv65o zH2VU`+gcCwxn(i5XZErER>lNcvW44NNwkG#NK_s$N4PrEBTGu{RFtJFN1m%8Db9gH z))yO%am$TXt(y8Pf%5*O>yr_-7INAQn=}}Ku<@>ioQOhMum0pNF4cUmt0q;m(cbNC zI@W+~m14awiiKp_1cTMO;-I6p{KvK7GdD-&52Ec4^anZu0zRmFM((1%L!(kvZnd*n zw5f?FEHmrmK$)Qd{wZ1V;6#ZFTn!>6P&H?Vb#dw9Lg#yGptq79hc91F)h{FAr^uQR zoS#QOu;zIy{A1PGj>#}4Uxv`xPFq+AY`=l&rF18cO`ZyQ7LjrkzmG*G?nlU=}SZu5VIBOCZYrkh;P! zl-A5jHdCyAFn&TB0v+=kLZYS>+!WGK?91)g3z5Ru!m3@3yXjefj^T2Q>y|N?cHNZR zO;g|?@eACB8<)WLPg^CB_>}%d>5#wLsAWkS%+eZ_l1$>9vFN*I!wR`NFmIqKc^;p! zClPS>z0vB?wR%@fjYEmvIKcodNca5&FQn-@Gw7`h$wx~?NA+5S8NvPm-18E?lFG3o zOs&>Q+R}@mA}vh$D8VDTQ*PnYDodpV_mok&G=_CaJq;0zSH`>NJbDP?CLiwFb3R=b z{R%p4D7Vs`p}Pz@iKH%%5_v*aJh8SCB0uvWX$-nn&vW_;#H zNgPX_huzYJ4SU8cyaZPan6+eSe<iGC|9NoaqhV;^7*uw9Pvp~|D(l$}w=Y9f*tSz#^kM56d z7hi;brakzEZnSFlb-l*1eVpkL^fg)~15hqS_lvW6r`wO?cw8Cj246?w;>QdZ)mN>v zwvJy5cDpe6kW<-5DYH3~`p}w~=B7?yZ|d5!eTxX*e5*b6HXFh~dTyWLtEEaAbzHTO zx70VS^L*kQXcFVU4Or(IV0JhC-Fxe=Ca0@xynWo4w=>wj9=9jC+PhrTX;kxOH$+07znIW z?^OcTAfb*JB~_5xfH-ArE;$@3D+2Nf25>)kqvp5bV~_cjH6)>wRXA)D>z25$O>t zI@hMnR?EScoR!ShL*G!(6=V9wRIRn1|u*w(f)^_?yABIBxLqq2P6 zrD}rmR9k+=XDnB*hC;s7$(DMnt{EG?s}b{L{BuRl7PY>GmSfH8_l5u(@w;%v!^7mVAxUyB*PjapwOs#6J^Tst_R_=Bx;EHglBxnlwXoC zh{Rx^n5|!M+kfk|YXv5*Dn}gS3X{0yE+Pe-UOuwQlbT%=I>caa(i(2ueOS#tYavx-ciy2$wY@A|;o=`s zznoZMAiHTfRWT|=$av4+bL*g4W5~9!p^AHq+A7j`5Ozzue`rDJfO*w}0`h7(mS zkaM5gXL|*~AgI-y1$bz6X&$!E61-=jL6KW!j&={j%yS~CPAy45YS9^NH$kxv=M%P~ zA)tBK8BE6q%PTNLxvAbtFi0vuZ91M`bg1y~X3tqB@y3#!HY1zUgZ=hRJI3HU6P#jY zr;WX7ng}criXHl~cr|}>{PYe>JdI*=zUd`uryvE1!}smj9K)B)MOa2lZd>dnxv;HG zTCangykHgu5kBou3D#nfNcv=K-32+l3HQ0DSBo7aK27+3=HP|8D26(R=<7*MNqyuG z17#?t$v{R`K;v-TWuVC9tO+7OPiP zblE3>s#U^SYwA}2?o~ExU;TE?cxgUHPA<9VtLoMmbuT^Ds2`q5ne z@#7p%+>cYosT3EAy{emEvCFSM;Ku=2#!@x+Vze%;9C)5jwA-IBTq7Qk8Y5zUaL2Vy zyEpn;wf4ccb){wEHDs;$7O+1_H)rg8bZ#te>zVw3^yrR(etNVIvE2B^?zn~j?AFt< zF@O))SQ~Eh9XLu*C3DAs^xc$^NxTvJtoh*$x#7k8D`kvNj;vO{z4p-ti%t_mS}BqC zq)v1dj>hWe$EJ;%P_1-oWn11%28w~!8;PT5l%`3~GsnUc7aHc5LAA#`pp>OwtjN3Og z-Xot@)=pZi+$Rqs;-bh9dlk0f+i*v5##EYG;^3hmcUiVAT_yZUO*R%3s~u+c`wT3x zh1bt;r6op_QcM()jHsb*7}RcfFwtwgzy$&zb-CWRt$3p$R*?&oXY$+gk7rS}Nny#; z;<7Ak;A(~$wd}!N`ZFk{yYniN8>FEC zW}1d(JGD-28>HgLq{ zxiUH?NDTT8q8{UGd)*J?x#UzvU{$cCsn9(0@l#Np3U z-L~6mkN*yLy*8V4!eK_p9=~A|b3F^^l9=rlHJ2D+Cq}%MP_V&#BcfM(KWc*BZ-Ts4 zhuB)Ho}N{}*ORTX9G=yvweeozrb1xpOGFU6Qqave@H5AUT} z1Tnw4yq+>V5`IQzi`v!UXEd9)2!8#J5*4iI5&y>W`{;r>ot4#hT#?_MvssP!8v9q< zsd|Rh^6#tB`+HnsH%pA^e4K|5p)TNwAS=#$=Ms6+MTtCuiq~`3V5R+US>O6{3Uyra zS83jL#n&f%p%8Nkv)MGu&fgt!Ph^tEw##qw_$m9^jUB)X`#EEcS906D6wwM%=B!X= zyJZ=n&CLnsR)CDxv}J@jh{BtO66$)=`MWSa6%!YB_FSuRt*oUdx^)=ck!0kXTdvx| z@B3iIn+`H|%JV|sY?Q%SWg^xA{rqYwD2jZgs69I15`Ly;r3!!Cm{N#H@3N$HhEN$1 z5fcHoL_@#K;#68bJfua-u+%6Ku{3!>TIv#E<#fr{Y2Q$WHaMO5C+;U%*~G5O5LZW@->j}B7vM< z)U77$KhA8v=Z@8*uXt18PTTKTtC7Oo>uH-zmL!8*uunY_2fGwf!CbX*o7pmi)sud* z_MrU+v-IK}psZ70ZH&6628TS-&naQt=AE^TNW{Y{0ZcyJ z0N7;PRo}>y4<<6?2Rq*Y^JSr6o>fYQsY8neV5^}}cE`4)v z$#lX8k)mm)*s@4&&+wYHJhi9yJ73hP0arO*#Qz^{cL5bgwmk|TOMqa(gS%UB4G`Sj zJ;B|AySr;}cXx;2?(PI{+@Z0rCv)fCnfvB`_y68oZ>_WT+O_L6Rn_$BI@Mi$e%KL~ zMi)sQYhHE5wD?j>86LUR$iaG zgtg+bjj{H9SIZpSXk{^c?b*{=yqmL0J|Cx*rVUQ!uH?Fa9Ltrw!$(N&>OTTmCu@+E zKX<4QBi4G9<)Oo5b!H{?g-Ps)ABKr~*G;0Dzu`@BT5GZSj9h&dGV%T=%_cUHV%&bg z#fPR+j|>LE;vb9YRHGSE@-k46`x4l=M(9R-aKMlHW#h^Av|kSgqiMM$Nk91rf_<7J z=7>^nKQZ2u;~dqwLGvz4B^!=GBdTSytAdQzy zt36=DRV#UKE0ZkFg{evUmJ` zY@Q74{b zkT~s`E7_ry07+auWZqC@)!5$3H_zmE+Z_A0mYqCO9myxdaHJuGGlYzy@6IXN>PUz9 z|MZ#nWi8lWyhLW~V0;s85%Ix0hP2AL9Q4(Z)?2s!IY|8_&liQ|OvVW_;)o{gICdM> z<-|EINwxTIv_hXm{pKL6d)C}~oxK1$CHc=4#sH%;_AGt6t zdQ501P{de6$MFrj5e?#c@QY#*Y_O3a+boqdP(3|3m7XEQ?)Y8hIrO$X^KG*diD*pQ zC=N?Ue>fqoY=tu6OXXp1O|Iqy`8$$6t8L{gN>LZgC(jhB6@gbEmg<6rM1mL_5a9mexRMeqXC31p-I#je@OChqChDE#9$P*QbH06= z?INsg$rmDC$iX>)wq`rny6PCUtA44P9?8`a#cjn0qniY`2E!kh~Lg;6luF;(YOly(VVCGZllyq){836@7QFM~A{ zvrOgf3-wc6g?r_3%EE?EPiXv_ty;Taz2^{ugs7%!n6jLac%E~A0gHpqhdU-~Hh46l ziz(wMU-@BZCvPJ~pL(b#?fA6ZS;-}HK=@`(4iDl0$~q;bI_*J`8usi?qW3HG2h$8J z`wQX0qhdDKrL*G+GL6R}NU)t5z`KF8*8Z$^$8Zrs=tDwHLnGUSz!yQ388MlPZmeub z-E2r}u0$4ISzqN@o*3yRI;I1aHzodt^#R;UIWa`{+JJVM&Ipmc&%uH$&u?9`I0f+n zPuawhK4VkAkBWa)n}0^WTBU6`)Y^`^;BK(*JMDgw>LxyBGi{!ZAL$(_OOz;jlUr}| z6*CmMN+f8XRfkI>iT`o5CGYeKKjY(f8XLPhL~-@$xjXNQAJ2O~3=vLqm6wmo8)~0@ zn=gE<$AYDM4buoNfp;;u)F)!opSRvy>!+P}^xCoTvD2h=gtb%j7i)0F1zlRC2)g9D zphYduT;UU~53+rVh(}kIAi4j-^JD%1!0Yed^kEY@TC+>yUEsG*tRC4UBUI~S^7KfO znen^f9)I!fG z6E{XAQ_iJ5q0s^2r8sK11^B+Jh#zwB|WWhd}Fzhf#*6s1EK9EfK%MJ7(MiKC8i zjJ&)EPl_LrOrlox`S_(>N<6paNWE>OgtR6nGRv8LBv@C1&sJ28ZNMeTMwA~)F7li) zJXwj!fH8}dB|Tnk$SrxjaX+HI7SGSqR%SR=)NgXzB!rzQqfl(;2NU=OcMFZ?8^j#^ zG4lyTmk0?{hIn=3Avm0)LOSj58PiizB`W**Uv?@|#REL(7M&vP;f$6zWp2{;F#+yo zvMAsmF7x2y3h6k&uT563G6G&C&1oH5R%KX9xkxuiW#~hs#LG42bNTF92gcuc1uA}$ zVg43WZb!$rl(au_=Ie$MlEZwKE;+)iT3jm97aso|YyP{>kV6Dj-z(Vmd)cy6Tn`6+ zoVFov1x=KA?oGP4P@&vKd`(i|o&~5lS5zV*AJ^jjX{;Wu42EKJ2aB9oXV3cQB(Acz z4rO4l8E6$6v_xaDmlD`25YiMClabFpcU&iRyL$ncf5QZfii@jzbv^sdhd>;8pZ6 zB`l-vgoYRYn~c?YS8PqC@%{_i@g563yo%`kJ3NR&;CRtuWpTz?}zemV{XZZ-$Q4ity95prV`i$nfb5n|Y$U6aLoM_%-VZ_Qyw3jQ#Q` z>R?WhuDw>UauWh8_0M49wRK+HLcv6|=6QAJXBks4?I?}5-8crM&IsQMe}X|JBSOc> zQu}bZbXH&ev?wp$4kz)QM)b^*$PL(c7;c59{Tw}Gmaq00;w$dM6zP_$@d>rI20!++V(8G znINN?i~y<3D_&$2qBMs+@LJ_eD>e9Jcgj&f9&2{V69TF+cVx?8gV*OVM6YPUffCxm9>^$b=#?Q?&lExROzBNJHkZ7K&|irNw|s5r#Xx z*LTsiPVmcc{U(WamC@uB;Wd8Gkk9&LdN(y+r>|I?d1z%{6m&{dR3JQ3kPM{a_-uw4 zo!wWJl3Qbo%lamg2oO}jREML2eLkl4K`HGpyzHaoxk`JvILhhI+Mm*T@i#E?R%O$( zef)r5IYNj3frjSjk=&I}75z%_#m{pT;S@gb{to&KIuS=}x3Z#T6~PMcpnu2*YuTSoY<6n|@kjn|3Iu zd+lWY2`LqbJ&Lc%y0}47eS5aC`7lVNgVxDI2}b)|h}U-sdJye3@qx2xg)RqAeJpul zg;WcSsqFO>`P)#fsOzL)?ek5Xv{#?gE$o8a3c2krA&pYqDXZI`J0-8|0EuYV`mQD7w64m$krqk zC(7C{w@XNny~aIn&!cN0jIM!2A{jFgHAZ_U`90oBaE(!bR@7aBjaGLxJK-mVd4G_Z z>6U4|LZ?k>|C!W!45_4Ezi8S<#AgRI{deyrI23J=T=9s<5?|1Xi3N3WlohD8sjEmn zIPmQViHOHsvE2-blHy zWArRNfumW&^mi#5Z%i5&vK){Tq{_=C30e!$asqPG?w^6@1tB7bD_rF%wM z&s`T%Gt0X8^l>$)=q=vQg}CE3wOXY?rC9345GiwR24;oza-o+c?St&YFZUU+CgIRE zIvb}pt3p~v;P6wcA?ojtXtZRy{A6{JoI~}7GBi+KVKd`y1PLI3d8E6y2e;+x@49Hc zSU-2K#p)$}A73aa-ih&U7RWUl_jMH}z@Kk4!X22oHX;PP|0Z3!ZGaa32!VnuvOBA- zJSh02yF=uQE+%AfMoCKiGK7NsCiyNCVsC5>h2Wr)cC+mjChcylMNR#D+K40VGcu1% zE#YfK)Azc4SPr-|tMm`phMeEFY-zOItQ=+vM?HAb( z2x=gVOqY=FzvT#<(@2$pMXR+*>cSTdu3Y@#yuI-T&tv5kqK^FQYfrLo*5gc6odx#D zM|SJj4$fzJum7FS=HCXd6W#KnOMMJ7^|^ z;7qC4=R~xRq#(OGX`8C!xHUnLN8H1_7>LZ_FBI$F)hI2Bo$YlDQWUHUWH>fw_+W>y zF#~0~ghE(^6+$#Np3=5s%2^>_TdHo+s-e5298xQfsyw_xk=^Y@I)#9-!BR(gS#t`O zUdnY@%@~caenXQNtfMn4OwGDPPnm;xNJx10p*?+hhql8Qjt7sKwb9H(R6!K_LP}0N zg^6-JYm@HsKEKFfu2#DaEsU=AK z3`MRx1Fv?t2tO%19UI4@_*`Jh#(UZoho~gHNXq>3HXLf$Ngno8f6V5TfT9Ba1572= z`w&kwUEz?%#1zI3$xr@{HVjk_VtIu*Qk4i)qmok@YBD{377q(-mSt6ko0;Oz~Znf@t>d%&qu2geGnc3r{r|#PZ?^DsP=*-}kOekGm(~)YQ0~GYH!Yp2&C#;_b z`8q4|Xj4ndT)jk&v)u+J^RZaJ%=*XpSDrzbSk~L^TIyXUmP3wDJ_wQRn}4ak(4|n& zlvYabb7FKXM*rCdDB4XmZQ1^$*3j8W&!OUr`L@oGjTT9aTHw7nt&tfTa|-!U6_eqo z`mgwdgWNtAjg(4KnPPyZe0oBr7TS_ifBbM^WFQsFMm8!1U3Terbx&!$u|WnJ1{*&E zN89$J%!JmjiAR~=+rP38*T{@?D7s{?P`JIoH(H-QU9D|SAOD1`*kDs-9kCo#IdSrU z%ds{tU;9Ry7?8$Sb)+gQU-=QLUug5f`?qMP>mnzI7f~Zt zcyT{!``K9jV-G)YFY3e^!OEeLwfFc{!**UvzvX58X?@W6`v!XIS;Z^&gk8Dk%gIfv z=5wfZL&fBT=RGag0yXPCz_@~aaM@J5Z(CxtFh-Mep7418?mqoNdTODJ;k)OlvXWta zpOXkZja3~N`aoHONJAK)Z1}YT>5pd`y`fv>pHKVWEUL@S0erwP^Ns%_Aj6;&f=Jg*%58%^xDK5Y$_V$lTlOVe1Ib+ zBvwYYfxOj`D=VU8qh)!6ESyII4teT!=HWPX_w4C;_BesWXMgq^Pu6@l{%N0c|1|kX zL!)B5yZO5onCcp-_f&6NAm_5$;2htxGLspC|6)JI)Eh z{kRGo`M$<=hla%Mr?Q==0{QI~^7wX@>XdC?%($zh{`$s7B+wdG1Ipm~{e2 zBe ziFc6{&#i&0jdq@OR0DYCLv$^Sz?@EqZb;8Uyl3~t@qN>0d!wJ28J(Y$!9!lShl&HP zo=GO4+V-fnnIO`3UaGx?3J&>R1$cLxj?{-99^1Fsqu_|AF)j)AlN>tsnmdOq=_$P% zenJ@Ay|yNrSKvD0Ibj)(MSz4dE$uGzRnX5MKth?U_-pwNCq%!g!R<4IASeCD%rwE< zZKgpi121~&bEZn%E^(ipHoHx)WvCc7xHh|wNf`G~3%w5Zs7=LMNDDtAcKdBTpemDb z`Vyj-`{(Qt6%sR(9$p8#y>?uQ>ut4HP0kWr&(_R?=jnYXMc~t((aWN0_hqLO!!GmImc?AsZMr|B;MsyggR0xaTDCvVEmzEK zIn%MSpUti?BD^3@`;e@B;5}a4lGZINz0CgKZlMcw)k zH~j0TgPWYYnEmoRL-wi9`=AS{E2am&6mKSw6b-WP?nguC| zR1dQpC->cT zr%6c-2PTA$((NT?JPX68Gdj_j#I^l>=&RL%d90JA4{Y7|XKO=cciW4{H_yiX%gt0} zy5HvA)LZfAYbLlMEqCaFpF+yRU-^vCXwF_O10t{HRVI{QMKO{yrgmILPhfKLlWv@O zaC#Ef9aaRdooXKrt}5=mEVlz+$Jngy2^zq0a*aKXEgNH0dIpz->?Y^+LuQ9m9$w3L z1B4vkTh0j?({VOd)9`RM#?<)ELQuI>oW7de@Hqfkm?(zai3Z5zD*FNaR%E*fIo#1t z#=GxA=3SZQ$z_OZZ4qpj=!7PqE*%Rsw(Ylh@cU5$%Ao5K#NJmDePFM0THQ9^eK>i& z-FPAJ^0;~333`q40x#l`q!N9e@bc8k;@jWf$8->O+t0i0h?KYNS*B>1p}{mjaZTx( zx>VuQxV^7s+Whu)(-0Zl38_BQ1vu(YXjlH_%XLqlYX@IsymV#n+gEWVlpumJ(B$m~ zUzP^>D>nn}-#L+}cWn>#%Iq82-q|48!8PZv#-*jYWw=GS1w95oradOE{5aV~v=MFo zd`i$s*a_3=+{x03+xfMVx>KVw>^bGR;-{vnc3OLx6C)ix5l^7+1t6?IsS^`HT8=9 ziu{t|mHNs7(#XVL8XqQZ&+anMUXx!XURhs`o^`Lidc5LZjb6)NHXhC{H}<_IUz=XP zgV7U`5>gW~5|U(5W-(=vZ{~Oxc$Y#1LQ{gXzYT{yfIomuM*c{#>ErzdJPMiz`TSd# zJ$U6?3;6qwdXio2;46@~P*3d8UdUFcL^8qv`rqp{( zG!!)S_z&^O@t8{325@#z+SsITv~gxp@}MK&0Wc}=SvU`Fvs(R5kz7el#3xI#96nFH zZAZCwoP_?I`Njhegq2Nv?tFuX2&6f%u;I5+v$3#|uyM5cVk2Dj>Arijf0M?q5-HJ7 z({II(+t1Cf@Xf@#4)*)(P2nFSzN*kjP@V6eT+ds75I}n&x6wHppELaMf+B$9#XE+D zMGS!#hY?2_LZE^zMl6PFCKZBjCN~fY#+b%nqR-|N#zf>H2i54WH5DcV!NtBZeCtHd&q^gS7gc^C1_;v(6@raf_%oNMA zxo=wkyV-Zs=7GyB!)(LiUGcD$%eGzC5$?n&+Dy%k`s1qOdfY19dU%b$;mSBbTp3^z zM__I;RbU{{F+c`B9obd&z#|(eh#pZJxrO|j;DKbebzlc3Q2Zb%dn4!+@tO5{ViGmm zE9fCWy*sBTwwtNvvS+yaz6w}1(oK(qgRuwC+$|EYhU;j)7+=NRz32bweFNd~MHNMN z2BI7N@my8J7lJ@b*hg{;HxO91(G%&P{*D_H{{ucgK4u2C6#~P%O8839ZGml6PbKGD zTN3vXTl(DtL3aVNNS(~?R`+e^qCH7LeCQp#Pkra?-RuF@h#S~1+V>Ub9$U~oQ9+p@ zo5TXdIm9R=OvIPO5+oMLk-?HAdBNr+X~;&sW5}P7XGl)Nn;5>z_m%`ZAWw)`gx^#C zyb87^aTGd^;COG#^7Z4-%)zX|;KBRBy1}%;pMxcX%Y$JgsU($=ZA1zYZB%v^2C6%~ zgIF>4!~~&QXw9^C4mrp@!Kxq*{j%VmHfdeJLU{zm0p zsc&}QRK9)w=2G|G@rS6O;3j(~(mYa1>A%u=V72*v^ZwvI{yyz~+L`Dj$C=Sntqs>p z(OuMC_UZb5=>n;jAygN+lm6x5p8e-W)CNi?ou|{2^@Zs61nE76KLshN0XZ7E5*Y^y zHcExWhZsH5I*M;(QZmWkKeB)E?B0egMP(yxi#?YCy|gP)8YrG(&qcdK{A)u#hscKv zh0OQH3h`ca_wMzYqiTm3{Y>sX?WGE-MLCmpr?i#-Sp)LQAVU~PJ2LLAeh!4_l3Gcw zrr&G+oa$v3*HREuP*V7+Aflk7;G!TsEi5iAu1ba=s}O4?g&oJjTg+hUI-M?VAGb&L zDW#6*usH8VoPoSOrjE+getJIdEY^|iM3O7{8_%H>Qxa}0ZbDjeT1;A!R*HqBBdKl* zEtziWYHS%rl+>wMMl=uS!|hIM+?lK=sf+k!$&SO&1Vv}!lgy>)P$q>}Y8#1*^`*~F z?vUTmYaUd-P+o6gUj9xVTA@<@Y=KtVbef&RFanj?ur!svVv7QK!Khd>&2C40kRnE5 znV5Q94bg6XJiFq$z=fw`U%w3kx^C^Rj#B0CNvVW-=vo zGhe;}aSl_b*$b_uU+FzmfgRU=hXXSc1~ynkSn^mQSXfvtSov5D@S^?sSPK31Saevf z{e$6=;jmb7%vKXk+}khVqD+YfWy5Mo7Z&|ASk}hw(HH9d3s`(cPiYsL{afLkOyfpx z4FV1OjS38mj4_N<43?Q0MlD9$n67|QoVBdApK6(F+3hv<%0}Io35K=en`uE{8UG&K z_e$fA)Cb!=%f1Ffwd96tiLBhEeCD3>`sy^b^G2WIZtUhY)z6GQQf`#zk<|GNPbRqH9hl51SNOPD zxXHOWxoKJnTX{4GI|y5e9z&0hYP6S(ZV!$%YusuIjV4ArC?0VC&z3L;>h^TFso6h5!SJw|~n71!3TeL5``YG418{nCr z)X3D0SFIbiPXMbNsvQCxA{_i~$c|Fy@5(aOI_o^G*DRmsfQ2{yH)pt=xRNs8WE5nK zWIScm5i=Dt?bXM3IeYBVI7P;b(o*fM#=ghei;kzILEB;M@MK&Gjn8mS?6#%UGVb@J z(Q$6Fx?dl|O^QaEBGdf9~-miA7 z9yUAejgO@#J(`?et`^!Y>~|zTikud#jx}rAcaE$jw1U11IlWkAcG1!i(@_G=93i5k zqhp#uHxc7xni210sUw+@!Om1kVlA+~)3$PTI^N267Sl%NQhGVR`ziHKVtvJhV8ug>U~k(TM}ZmDTX4U^BUtt`}*x~xUyJ?>dh2iQv1x#ResNBnJi3Vh1dTKW1 z+E{P-bms>61-zoYK^I2r!^}tDMMK9_MxVpb)|%D&<}igIY&IngLd#l0$uY(#TS^Z) za)QDzFv}@56zj4N@^je3)@guw2O~LWVUC#38rQ~CAvvJob|_unRG)a?_r8Zd!#;Og zj|;=TBupe4M+}_4+)!)!j(TT_3%ox2Py$LFxhLlf)IM2EKGi3)i~gTTVU1{Bif!%A zvKME4qM@?rnKZDpunZwI;&j!CXbDP*v+-I=(@J*AL+2>@JN>bYWZNLFtRQJsovG14 zXDF9!L^6X~UH9_q5DrQG0lAK8H9c)VRcQNDbBNIq7+OMZTSgM#Q` ze!jwCeLh{j>*3&ZAQx2$pxRB46_@V{W zJlvY@l$c0-6CaS!mzW=Kn1r6F9KSR|Pis!wT5}9!YA&lUYcH!UYqZcAs6jRKN_tGt9L^ny8)hE48W|aWxCCB~3^Ong zsGQQW4~r&jXnC4H#9wj`@5l4Wb!0tVTv7~Y(tA}r&0R+95+qtvy%xB;J!D*Nj6}s} zQuC=It0C(ktHx-2DW@zcDk~~(D#|JTSrWR1F3}f(u20>sdaW!~*;M=0s;@0nlqOM? zN4dJ=XJ05gHJh?U#iGWAc3(xP2RbxOq-t964z(b4E;T9*GxZgrdZrD0X-jfz#J=4KFF=9JJ%eW#3H#-oF- zgRTlP&dRAvO3F%#TZ&4G0VO3{${Na=b4?|uCF07B%4_PNPxE!=a+PJ3K55@*&6O(S zl=7A>E8IxW-Ija;O(lj`%%$v5!Bxf8##O;pzpSCHq^+*4=ppZ*c%uv=%Mt)Mzu22etyV=N?OtR0t}0^|vjE8YneO=tflZ zXc}P~!YrhH6+b91u~ygGD>+H2Y*Zp$lH zhX>dz+}V~&+~$jutCNECN{)`Q1^W#EGbJ`99_s9DHw!1#M>@-*lw}d=V{?K&2^O2I z645#D5@co65+fyI>JVkNtR-(F$P{UQLs4bF5)9?^VEVe;ZsE-(Z)3;|1ZOr-G5{F` zjgJJ9rGEnqF1oglQ zZy-K99yAJe;sH-4t%E$duUCFARsP^N`)JGh;WNT}Gw-sRF3X?LBQ*e@D-~5!)H2?-?fO)eN_iKIl#wIuJD{+=oh3B-p3_0C=c-DjIS+|QP=qbdnr$XRmIHy$!-q66(Q|cm{>1Y~`rFIE81nDd*c|b!av?R2_mp4# zO$v9w)5eW-Hr^9+WwXPB%ZViV=X51|6w%O;vR0pbbJ(TH4!1s6 z!*5~;Qe=9N=>FD}i}SaRxBRSNCE)MfxsWo)dkU}458dg!&A_3I$9ukC+3fM8aU%VZ zws9aWjP*EN*{tzsvHvO6g`RVe)BY8LbQVA}&9?`l?r-(FKznb3!h2kPo2)BD!miri z!}&1}4>!`p_(JZ&jhqUSq0KoDE{`r!`uUanr}!T~u6`{eK~MDjmbybK^-NryUxB)8 zfTbfO`@Su*;^*6Xa^dj8AI}WB+Q;#kgz*<4^hS362!SNB`2&XMgO4>7elRHf1A*a* zev34{`5Bu>%n#c1oDcz@<%b`+^CT2f%I0TO9ur?^>GLeuzc2pU!k;$wzn$tp;B$CG zL!WPg;p2AsK|0%jAt7%50B<9WI5AC~qNN1YxV zTaY}9V*kW}NfrW&gV93)mm>BShx!--MvmM?3h_tL#n+qXGk*plj6?fcI$kctt)rt; z#7V~N`pgpBTo7UnGCv!{pa|F!3?UA<0STe``(u9S8<;G7@L3XXS17qCFaR?DCx{|Z zu>VrrL4)`p1_lYMM+gp2>g@ydF&gYGN*Dj1ii892qxE418KEX)!8B0#B_T}2!RTPK z$iVAJL94oC1nAEB6(EAez>r}#alz9_yzQZEBEiOyyJ#Ssh51Vey>*}_!@yjT`57P% zgl(J&plO-jf@ArCB_abDrJ^Ii{&grf{9yYqgLI(1_eK-^(?0z=8f-AA-*!yEZ@cB< zM1Q6KwvI#}vr8DFNem1Vc9R%fi_|*|$|eSk9_7CmStL-olEJW1_yr+M#J~_>vxvZ( z!@O68!Kh#f$-whSz2l*xW5EJ zDqFi&xO6(>?s@#rB~MRkj|lTWwIlbnqO0tMhsh)N0|(xKKR3iofgo!w#7v_g+1j4M zrLCFcb5qBA7H;A{gB4mqhU>$gW zY@q_c54A_wQjxkAbW_hfmN(T->eox&D$`M4obvHe|p?TI;r^d=NH#}7oA zDnHa?J#cQdu1KCsvRYwL3}WceS~KUP+@PEO8m9i83&xhkl! zvFC5fqI+LJEoh{%XLn_5{>0|U(ct}mYPUvbZuX1qNmJ|=tV`8%1_LT_cuRr*=MC2o zT6F1$yrWG#-k(w)18Af+WYrxc1&Ey1P z)Ylb(E>SRU>P)hPN$65crljCvFqAUIZbJS?LFh(YDf7>P(XN3=sD?<07(Ghj-%r48 zT&Z%bxhV4DWoCbz1OAX8{|y5B2N(8VAh3VfV1K8G{tE*8hc)_}6#DN&iN6-&yeWPk zTNt@F7#RuW*?|UY@h0db|>Kd@<_lmbdK{e{aV8?#ldufc@D8E2;@;mQVSY%r!2N8a#n(% z<}SfjsxJb_amvl*UQ(M2&H4X22RW$Lfg?#u^v0r8=LykLO}*tQqeZ5X>>Wm_t`RDu z1uf&8SB(pmF(V&I?fCp<{0kZt|9jy-@vMIUYp`9lkQ0bJ+~;~)#Nm?uwjm$sk^9NI zn}j|j!EB>^`QIphML5^fC$^CCj|i#n@+%Jc$ckJ*-aRXnoC2eW`o)Y`O1kU~KCO&@ zUq}@PG6qHW&t4G21CDe{(fuN{n5hQMlbo&gy8u>+==@Q>`ky=);CK1=4_N457Vuvx z{|f{5XBiAeRLGx%xEmRHD>&FjNQi@&7#A7zN&X+@>K~=3`uzW1{STf0T;BRB+@yv~ zuk!m}+_Dko&_YI3_3uIdl};Vm{AnY9e%$~2@;}DjUHZ-5(h&CIdi1cPWIoNLACsW= zV!O0Zk|jaKIUTxx4YrgaXTn_{{?od@eZapLd1JdoQSQYc2*fu@VBJZ5d`Le=L%ogd;z#))1_3Fq zM+gf~>f=gk6REVV9O&t5NLm#Rl^D~-grX(_F(Rgi1xrif^M732M2Br7_E9B04~5c+ z>7qe#7KW%4`%4j52Pz!qzx3&%QTQiI=VK4rRjBcpE>08rKNRM&hb01Z#5%4ErYpXJZR_6v7#H!*Abvl zv^~X+@9`_3PEvuVqj(d7eFpROrhoU_6+M4Fh*(yFlcVFW$Lnc;{DBC?{r*_aGRTZu zX(f9(l5vsoEw}eESPkSLA|dymSunx>5eqh{07qB<&)_hr08Qs`V2lS;5AvMP&ip<7 zD+>nsn|3xS3k^K{%_#rN`_eD991#Q*{)q*f%mbIk{uSD!CzIY@=YxBg^6O%Q(w`s} zj3@^h;ovjLHJgC-9|6RIah5#{2Yz8+-)z%Cv&OaE-R(I*aBm*p9&y0et%&>QY5WuQ zJY;IbbGM>-k1^~{8zMS(_4}BCyY0N1>Wx~WTs&Hg%)q#ksmDXcD5P!|cZl)rFe`lB zZ&z%K@d#{&e$pU>t8{Gzs@*StQ4it%B}K`^mo@UN#Km28Y`fKLJ&@I^2YWzuo~NT` z?;?RUsg4bPcg2JTPf4#?sng=H=}@hLo?&}^xj73mVCaw) zPkYTnk)jUui-D}>gwoOOwy4gRlhbO)>l=-g{_w+tW0NCu0*?;uKJ=6H^m+NUZHhVv zhq^lz4V*!$o}>EPy1RxuDKi4?->9pKHLezY3sGH7<9#J_w}qn9DWReJ2KjBSmSypt zhAB%D?v?WPHGLp?<4v9BzYh`Y4_?fv*0#2(z<#N5^mwUq%*n=b%~WC|l=v zt5Rj^X}P-ThO_^A>znX=@n(GE44*#u88*Nc zcObydVHIA1-R`?5(qyM;?}NR*_@@-yYirqXq5EmAGwFyHycH;9a!q(3D_g>riztE>evCJI=(oZCg7Y@yNp+=RjP@Jkg05SI8;p zl{HaBAbW%k`2bv=>@^Zoy8wVJ&(jYVXXt|5We-oGQ##UNC+qpu8#h&~6-m5392air z0*jL^t|2on8Q7eUi+rRoVtPlL^~<+0a81e0Vba-ICaq~(9LHzdAlqMoudIZjnPNeaaZy? zPb8Nr1SDn_t7NO#z{act-9;GEFw$g}x@a<#e&N_HA$vwGT1?D%)OehD%y z&W+31j;dr2A9rI4=}CRzmAT-U2Odrq6_-FhwQQtZR+ z6R%wM;VL33oV3nb*qYbv+s}YqH`zxd3j-Bn6|!2HExh)YwjQUz?)tf#{3Du$g$iq} zjh2Sy4ttL?;E$VJ^H%d9^Fs3^^Ts2Jg^7w!73~$eT8~5OyOK2W!VxUHf;2MY5fx6+@r0`#_hx?j z_^_R?%|i4EBRh7@0u}M4J7!DdS2ctyyV%Vt6>)fW?e0GA+3qp!)$Sqg#qQr%3E79G z?P_UH_`6&5FC*lYa_d(VX+)ltH@q@fe^;2@2kf)Xo zHN!t_BJ_gXOXq26#owS|Apc~Q1JLx-# zI;lFzI_a$AH)1vt*oV%B&PE6Z35E%V2u4zOWp`wECqR~LPaqQs6Qm)Pf;1%Q7j2M-L_`q(8vmPy^vgo}mxSbZ zY5EZU)W}1cnJ_W*I*1>j_=M&~#t*CH8?Q$uR85&Jk&IFyL>VIyk5b-CSuK%BK>1xFF}7SS0hdg5NbxcOB43V5Av6IcUx`X_IN@EsLa{;#dTKX~ z@7I4wNR&6jZ-xVYX-H(l`NM`1e$z!PRAZqPStG z$)T0Qpbm={P3RleA4b`=H7u@?Qm-hJQ=u-6r--LWm>X6c#x^Xkk#W)ZjY4uY^t%kd zEW1p*Z2K#KblGwlcv*0nc-c@R{~Lg`l-E|+R{1-Cc@-NdGeH27W&%S( zWqf6Vb-ZteJ{;`Uuf~U$YrCWk-yvK0mu;(uOuG6mfWssd5 z2tdliRf(h&P0$~<-SxLqc#!1Gho>$~U>@EWj&vRg`atI23bMNPJ z0!zM_HDPCql*pUaVdwUj*qXJaWRaJMo7JS`6qJ~nwWMSlm8hFFm?_)OYO%_Wslv?) z)Qi!nNX{zMOVO#)%u3Wtl&e@$SH3IJE|)i-0>{EmAE}EmkdEC|W4#nLV04n%e>(0AT8c9ZKkxRnV1{S(Q~0=9Dz&aOP5H z*&On?B=E``O7&-}0UY&$?dt8qCrSgQ+GdShpWBsBylrcfr zk>u7Nu5S5bz_M3GmiAVB>l4HyNO;uw>?T7anIrxSyl7hnm)CT0Ay=I(s^8WbR~cU*}fm zR^Pnrq0#BsdFy?fbsNnl>!y}k`6-8P62mO4PPD#nS$`Sj#MZL7K}xftd{V`%w2q>V zqJC~!aT(jPyg|lI!`>Wn+11kTHvG2iHtn|U*7r8&HukpWHuSdSHs!YEHt@FKHu1Kh zLEcT&O?4%&9VDT8WO)>MK0dro`K-(+TJS1x;kAS9;~@7o|pxkp9rJiPfx6VZD8W!n>f zM}*zPL8wXNv;lUF-03 z2LQINZ5de<0CCrvjGRJ%scTC{wlP56wZUr6{#xsk?8E}xwLrTV!@T76pD83uu1dHT z?aC?h8?LqNg(J)ZOaSH~=26l?5+Lai!8Lb1kNqfz{xIoC^*|M%dZ>D|aIgUAxjwo+ zy4eCE0AbpNodERO^XS@htlA3*YqOd+I5(-+Y#w>M5(MRqNBY;*K#q37PW4XVv)O?o z5Pl01la$Y<+-`V1a(Klv%Veht0W;T!K=^02XUAtmj{;uFPQ^~i%<_%$iK(-xv$=i1 z-QhFv83+mV0}29pp1*i>yaadf>lQIg6U<>AMIB0B58UJfnLL_11ayllr!yxrXH}16 z56!RZfn3j~Yvo7>M>hySW?(JQ9(VJIf+p;x6>sf`@33a@PIxz5?n>CXAism{5^!;Qm@BfbMZz{(9C zP{t#vL-SSqRedA(Y|d-y?ywW^c(ZZ6aRUh?0DgX!eUA22UZPGJIeI3}*&)LDNd{rq1mMGv&HS;pMEsFWg|MbX!ja8;u`Wb> zV@yb~hD1VR%<`}fMFL|?4X~C1=LQ+=BK|+l?kTvkE{qd?$4)xv*tTsO9oy>IX2(v) zc23Z-?c~HdNyoNrPTrY|ucm71tEsu%Rr_Mqv)0Ahdp+y_<0spsW`>U?En1>xk&R_7 zS}S9wjioJGsm19e!FDeKmT{aQhATVh8R`AfGt;xxGtslwvtY-Ll}wtojR-T-v)41$ zv(huyv(q!xv-xt7*s8h0@VKzaVlW4+S`n9jBL15}TxUj{`}O4-*|V%6`wh}zHnAMooSiYDHApNf5 zE~9C)Qwz&*>u~F0y3Ly99o{1z3N{KZ3eIgzc+PzpEgY z=eEG-QpBc;?TJwZ<~yx$n|^UfIF_+4|8Yor{~L$I@PExAY5f0kNESCGMk|xJ4GWcQ z1QuOhzr6~)61?iXBE8DJGM0@vGZicvXfhMM+Pp%&0LSe5CAPFB*48EVxFuH2UxX1? zhTVTW63>b)*KoS&q?1LsSA$pdvQ->c$ArC0kXOaB=|iU9fw)T|&vLejB1dV)+$7F{ z-NE?*!GXL>s#mF38qaFyYPRWy>4wb|$0ghAW_XP3}6ke<1qv7l8oXCCX<{7jTK9@gdv<&``h`O`rFvE^|1AD1uzG&w`B26umx~DX7yzB zWWh`bO#~n09gy7CdJXbh6SBo;QB5Qr7#`5L%<$XgvV3xePc$6x+!D>rjWxYAy|h3# zLN`Mgb5+4(JT%lIf7?7U>k}n(CP9?&|F7qU)gRCg~*Us_Llf&gsnQvgxqt zHt00yR#ov-wN-glJy$_hg;q&a4OLN80jkWa_N#tWrBta`{i|wThz>6-x^g)Be)1e_ zqhy%VIx_&(p-;#-asJ>)qDUG#*Wcg7e2nTmyjjHF;rwy7{U!%fCf<&HBJ$YCX&~(4BeVJXf*QG%&^9VHhoEiieOf z@;0ksY?nu>W{@Z6{fq~p93*f!5_q(a(c%MUS6vUfFAI-ma%0kN9~>C+{4iTNj!D8w z6^@pEl%(Y;XV2po<`Dm5;3CuLgQ_=1?>yYFxyv)O@<)olbm=Q(@(=(sihYgmMNz8F z$2i_UIOL%^WQHha+jw_P@`xvH%_A#W7t0DnrsP zmT3Aw6=(ncQCFtAY%C#CQ$TE7T6LZxpD^Vmb($Oi<*1OvPSM1CQ%-aBGPQ4zMEAQz zE?qtp3*eCO%JJF0#oY2rZzZkeNG;J4dA2&YXr23n=PV`8DbWK7BlUIy#$R%ci4rlS@IJNJrAhX~L9W20tL7@OmZHTA!E<#q%D`3GA zjK(CzPSUL(|MLlR-=S`>eBe%*s^`fby`QT?ni+EPrqxDs zb(A`4hjr><4o-z|b^X}OQFZ0Tt;fh16}01F5)@0tC0Hlc2eBXyyQInvT$IoOzvfp* zF_<2s!Uu_lO>W)5Fy+L5%7(K15Gf2t3jFq`;-V^Mo=fNZd0!1WjA6Iq(Y}#0Z#t_d zeS+(|<_o0MaBCXvy$j0P8C`Jp)D)CHLVKs*s~u&F$xYO#jitcqr|suTDBXzA+O~>? zGr~ebpBBIF!tAh~{H%RF?RzdIM2mNvDr``a48l}AyDXVO_ zjYQ`yca@K?KEZu$rTsAvB}(pE;QXVs-qQwAaV{QYSx05FF zs?6p(Vp7SZGo82m62;Jb@v-prr>L;gYypkWL zsWI$}c&BxZi{&oMXO6WqTNz)9@{T?qks3?Uqqg6i9a3Ns5YE=ei@xyauNUL{`*Gz& z-J?t6V0%`Cq5>Ms!84Q|U+h(olM`WDg{>n`uc?nsY1BO+5}@hTRLXp)q8{f)KgJs} zU59vrI@KAYWg%a=yL|pscMe>@l!9(JR6ay%SjRt8K>LPwfb&w<(c--0;DEV~RXBaL zY=Yz+exU}qV!3_IlXDuRH>sE4>M?5Xw83xVzuNq9LQ4_Dr`~tB6W1Xcw2mpt=2bY$ zz+MtzKIoJW#V~`D6oI`uhR064i+AYJMEp5wKHeKM9J;}Iv2Hl_{1A%qf)GMB8 zp=p(Wdy)7njQ{Cck{Yg+@+Jmkv6$Dc_%e<9oj$RevTXwc@|jNvCchz_1yUqE0r)FD zMl035<#(!~axxhr>x|}bj5*QmE|WQC^K5OanqNdF_eO&QE)L?Ctw%Jlo^{Nsrvy-} z!4N0fluM%=))yTB+~4_uMyw*bfBVtr<_|dxqLt6fy@7Sz4$IrWV2J(+Z-taCbH!0s zhY=}^o{}T_ndsOc>_i$%`k*WAwkE)wa6LV^D&rS~Kr(r(l8+oiT{O7edC_U+>2>() zxc3|q=yLF21^bIXU~2Co;}_4QzPq~`^DR0P8OHuinJ!Xk4QUco^PgWKVge#3oQL)5 z;~HMOe?4_-%~8b=Y8peTC1vRwrA4TpFqL)L(9}ybY<ul0I^P9IIVmJh}=b7msEAHRZ{|02mQ~9%=RrX;k+z-Rx2{Bn)FE zn&=B0MqKFEt00<{B56#HR?DBnxH7dozetQnSa^9bTjEKA+J@x4)8#7~_C;{pI?A*^ zC27*=ajBZzanEL2uCWkywaX^Kv7(%^G3hP1MSpjKOvVn2*9$=RE)lrXx-MmhEu{J6 z*7_53bD>T|EX&n%6p@ZMgE9IjDka40_odaI#-H^c`R4B%UJs=?@lNdrb&2W3GK5?I zv=h<$(x?1hI_JgU+b?Ly3T2XgF1?QZtt;$b{*ES6-FCNqKJ!KJOzwH7Ju(t05$24> z0$iMWtsdr>6G7xz2=(Bw5Y>6Wu~jW@?%U=JGsaen%hvdr=K{v)udS7r6(^36oL_eG zGcxbj0bbwyAs<)m8&IJ`-WP{v-Nx!b0z{1F{92_Y$&kS;hejaiHEeUF3z!OrmfcQH zsFyixCAOaOQv5frr)~TE6l)Do+x zqQ6JMmKycm|2C*Jb@HM6t9YwKbIta7W@z`N=8n(4(Y2u!#L6`|kU}Eo6)G;R_Ac`H zk}`ixZ%N@*YRuNg^3E=gEjgA$KLf}Ya&XxY+x8IqM45@!mC9oyAFn6Mp z9h3P=;GAo8r9Z89A(T7Ce34Bw?xkRMkl?@W^%{*W%aEgSOS<~vvvO0CqmFKx>X!jf za5(fr4UbDEAo@UOvYbh^(lrS=%S9K1h6+l$%&=1SG>Z+Pz?1l*XMN_O7&06v^7?ie zdu)k%c zBhuK1xw4^sg_}54svnA7w@xo#cvf`RZWFPHjtthkB&}U>VzkaT4v|#b1fW?$ll*y} z`{rHSU{C;FC!f>R$l9NR3^A!7=pIF0PwnLyC@f?H=DX$Ut-ed87Q6E=UefOt=X0t!|E-rLCjJJM1(neEO_xm-y(P1??UrS=+2-_(jWyCA=e zX(r+er1r2>c`D?X0nGYs*&T6;K>^!J{{z)8pgefKz(qntm^;$t`WsV?ic?0nG1C1TnGc zJ`dUYv+=G&9S~ctlTy#z4LX=lf)>U;KjLT2HpkVnL*=xeN5;anfb%`6p%#ljOZOx} zl6t6Y?P*hTu9|@Pt~<_VJ%?My6*9n5v5DXvs-euzc(`|YX$c97SLnaN>lseVB^^M+ z7nv0+%bU_XGavl&E47-phU)fw+0M%M=yvXR@bEG3zEX`Md2`bF@-fAf+RMWBk8D+6 zm2sPmbb6_tpn>B(UNzj+hmgV8fekWtzcc&g$g$KLi;#F;};*YGjtp4J!PntT;wWRV&|mgmFZg0 zU06;{)4hk0&&b@ua3O_7cGW9Lkj7oHY6;#>HyX1z#jz{-Crl9Mgo<(otJ#5#w_A-V zpBpF$AhhWY;S(V((ow%_m4(4$R?l?|k-wKt$cnkW=;g9~Z-Y$}so9@7M9Vqt1pBhG zmeabtD3n$mvqjIg!5?K=?^7not(08WYh1rpr+@_b=s{1x+k|sJN=}+~7;jh<+OmPh zDLJnDpX5YHyv3h*C;*U8at=&q78g|+4S@^O)dhClWQ8hQo7ENOyz~cMj(Kjy{JKzG zKq1!&?+6;gLeRsLAx$z5db886>xLwkT^R>K=^(lS5x-2DAwC?BbXu+?xJ2<`r`P)T zrVlgu$4&W@M@s#PoCZHd<}WFWQlhRl$4*^kD$2Qo2tcv^TohkRAP)R<0}^vntU+vD>Q1QEHbg|7afPPMWt>=WNN#4`;iQD!}8?B0R^pq7)~<(6N~oj z-hNdvlXvSQhkt};1p7w>kG8iR8;+dUl^D?+c52KEIAj0>(bE_tZ}-aWXk?BPg@8F) z>@znWL*-pEBY&Rwg7!sos%B?aio_J=xb}G592c|{l17e!1Q+nbHQ+=a+cg|xd^`QM z`xazT4^m`Rl3&d(gp=bgz~TJXj>MZ)jSQiPcxpCsyt>ABxSoBwIn(35{r5+O2EESe zCq0?LP5W(`=~qpKd2`Ak=;I5K@4orb#O}V)>0&gLG8Mr9CI}|lKsi( zl`96fxyjR|jU1$ur=}3DAVAZF7q6WzLXkKs)$%7_AhJEh@r6=F`};7>-n!S6fan_h zHtWfObh@yg#;3P9*{ZSpt=zukBk=7rkC)y9Mp~myb1# zq}7agZl;@MX~jt9W97=Fo+v`9zk`!o0&=8Hc+80J(g@N~e0<<17CB+J!VU|J=2mzx z9e;b?V7UBg;X3b4`b$`9JQVT>dD^!*hh?*)9Chnez&bSaJ%nuy&v(e)#Y?Oj`vlmP zIR2W1d3xz|64FJn%Ls%Ix7s^oK=In`8-3q!{4I`a1~%&d2@%ORR3tPu8y4IAgGzAW4T$ig{$Qy=UhKIQ91&90!Xt#gdE=nqu~?K zHhy>B_?1>nfPGaBhDI@ymb&{4I(4fr*R|-T9N@vzHf~@PdJYS#wILd$N@{yvld?mM7Wr7!(s=o0q z-ptfwL%FW`lDdzxS?@>b?Zzh8xM5PayFQ42bdfXMV4daCINUJ1+%J0*#5r3bl!83} z$AV}kdHFVUwJYR9nD45whF`eD;J2Rx>tM7DGqQ_8>%V^>829gYN>I{A&@GG;5ciO&L8wehBPfz^o_`DPX(Df2*$IPwU z>0?q_%Xjd)y@&lu5PKe%uobQnVNO|vxhY{8YadN;*U4eY`U>zwiySIj{eX3s#iDDX zO{8}0%SBhsNKh&*5jf%0F_03gCBH-g#W0%6@S%A!5F7Y95~rcXGrh_7Ub;N$Xx!Hr zIW4jpP7DE|?VY_Ae?rQ{8Ns5uDi%(?reW(qcC;{+Qe=#CuQYwzyI{P`rfLWpi>={QUW}mD~0%a*{ik^d1axsN?d=MA&J5)b)W7ZcjterZK-gCzRbyHT&8j zq;wd&Gf$W;ef{_?sz zTPSA=t~>Eu%$0b8>L;OF-HqGr<%-GDDdJs30jCXPs(owIrXv*1y-wh z=%IKCx!%Vps7C(YK2Fs+p9t2h4NJ+ghk9Ki(slQlAjXw9o4C2=_r%(LO(UqIYE*QO zyP2)e-!Q%iRh-<9*$L0>wp=kIWl>;4r3j|X4>wgPXc@QBEsDLtTG@(6$Bwk2KGROr z)?G+ytjd;oDO0NKvy!8z+*816)f-wwFBeq8MT3|9Q;R2!yK*JuUg6x?!Ra2zny&U_N$?~x+GuxpWl45uaQrtuwi zEv@bLO~AaubW-X737HU_beRkP>Dz9PUIDkqv)qQ#j`cR4=bMA6i7t=syvIYYyvNlH zx@|h1TQGyV(m&A$9lUaEfFc)heT*Sxh@AXgV>1VW@h_NmMf zUEQv#LIyABTNk+{XVR znvx4gel$C3Kto2F_~)QgoFq1Jv@{m#YOiJoe#LaN!cSucPk=UqH9q5gpEv|LsiKUY z8+xK+CslB6f}%lo!P0VvBTPP15LYlKvqv`voZ&$CVJx@HH}e>IfmkIrW;;))j8mD! z9%O%r&b>gr*b6ssk5)L)`JWl>tL?`vhN=tfeWXS-lAt?YK_?9NL(N3dmmil;ytg+_ zess5X8tvME$H-&myl<17{C8&(yu|Me$i~s>YHVmzuF(D~&&1!CSXOtmd|b?dk$_=| zPZ1+l7kf~pcWOT7swD+0t60WKqzmNIFaduS`#<^K`lk2~#;J!W2WKnu?6cORk(|1_ z9`OKEAqpg%SdPo+pCPOK7i?PlidoaL_>VL7&`O z@o|j3|820b?!4?rM3XT1sD$432g8p;ShFygCGb94a4Cx<&)J1lO0MtZxIeNIKIQ+& zs>uzPYk+$CS#0A=bIY805=TJEF8OAz_!Zp@L@X$EF~zRpiXj$7Jy1R87*xRLy%a@u0S> z7^=g$E+MbX|%jL0N?0wm+c z9MbE5^4WKZf1h94*hNo2IP@bXyr_cY+!PJg7`=R7-Ea<`6>M9Mb}uc;uDW|>vkJpb z28uKMP_{D1e7*sQ)oT~K961LTmir|jzOlseV_TsjKS%hhf;$UKWPHVi^Q$8;ymV2` z=oo&7{?4Oofz$rQ6QL5)NMqx%Be09JiY2SOq)6qTR-Jp~bhX~tZ&j?bxDz30q$H}z zQiqP@666BgU}1R=X^GvETd^?_`P>5CFQLsZ5Q|$VYr~oh#z$N{^_G#>uO|FLQ+KW1 zYr{V~ld!lJSNB6DKWg6@W^W1X>c@u?*RosbV97W4B z&4fC5b;WwPqG)=C1Dtq%>%R&)Q5Q=UO$hrA7GSQWEn_;jamw0KD6&)dEUSlPs|j6& zb-__ek0Fh59Q2GdizJ2xij4Z&D#PrbZE@TK!k0K`>=%VS%3nYb>j^79>6vKq+4fT| z#BoyKp6K|=$@P(8Mj-@?vX;x=|8aBa|C%8r`O$j=$| z<)YC0O^NTzs$x+o%9fad_U!=iXvL2N5G6DJA5f(K#LJF*xiVz<@_yI93#dDL%gG2J z$jRB%mNk6dbFwNywLXbh+x%fcb`<`|`bTgA4zl_?2oq!-o;s|$Az3+%Rb|==6D+@? zj8{M6KD%D-#nbxH`&pub2gr}<6%Z*b))FyH!kIen-6#WGh1_I#7ml!rzrWUiy$RoS@aFyz{Lu z1@3<64?Kejxps(6wn+3j!>5P0!2CE_Y)3oTTa7kR!^RL)lj!g2*_XFVP&gcr(rF21lv?->Y@unp?zadwY z!-C!nq~MrmD~|VRz4kH6JBporFBz#;wd74bDC;tj1J~V)`f+0`4b2=5r2XFm%TxwDG&$jt{ z^xM42=o(axMXdo@bOj5X^I8`_QyaV@fhk$KFFZ(}_S!TLJPu`0;j|~bTMAP8C1|Ptq%bwu8`K;Z1)_WpdDsMYx z3GvSN=zwFAeM$HHDI39ZF`Ym<$yna;wlDvRs4llG1y}r*d6}{}z57F{0!~hiEI5O> zZx=4p+R6r1gao2NRhlxvIRbrVbdm%k1v|JUDF3utt>+yUygD9og!T|}9^-;)B5LNC z*pC1i&`d-=DN3!}YDNz-zFabx|Lx~4=Nd^fobjgKXj?}n-v&IGBGb^wTEN48*gqV z@cd^0`AYtBQPXFpaZ!;CCoXd&G7l7AsUABqJs^LC#=#&tEBcQBVxYz~7s|#=vHyMU zVpXL{=GfWyfNbOz_9vz@PP+OYbHDYTLLnt#49X>Wn^x@0~EGz2+~u|73!~I#+Z69Cl1lRQv}Nwy$9N;+-FSvufp? zgYe&GHnqcMl>(D2QUu97A^$nCPs}GdI#6iBJ_b&vqf-uS+k3^9X=Hh`!`b*-T#RbSZ{49FwbO734E)3F ztU-&FFDJ(}Kq+`c`}B|CqK1RYM)L{fL|kY1(~WG^8A#lZ!*!7Rr}`Jxs!8>A_%rS* zZ(Rqo&}}X3>$Hz-n;l@sTm#O}U%jc`&Lg-lii4M>=2~UD9g@&uk-{zSb1NISx;N92 zfOWd6;!;pQ`1K4cjpGTf3N-AWlvF;kFeKSkN6w4Y;uJ9Qx+x)<&^R|j5+wG<*qxSh zTwW`Wc2SxvQ~x-~9V(tB_Ka~>&^gN=RKq*+NJL6H%-Iy-rKt4O_;!mg`>IDG6S++U zA0G%u19HH*`*Q^1BD!>pdi3A`qi>1|zGd@w^ar9?CWqq$R71w_H3m&%q?8k!kiO$| zEy1};lNU;p7?2#s&Bd!Z8EQ>YiXi)q^WB1wL*;pQbTCY?K2$8V+v^ytf7~D4#bK`( zxOMuH&0Q;nehEN%#ThNos0y_TDUwQ>GWZK}WBUL)@-|xG6|juNk*K}TS|*eZDX&-jBT%gatlz#U66&KWV~@k{L&b|uZrE3aSfiVhd= zuClF%HI;L!*h|m1Sf$hL)-+XW09z+hK|UR`Cm2~=AZ6O!L-@i3s9Q4f%68PaSA5Hq zW+m*xx2N!!F9skqYr1!LP^E5ac?m{>|IMZ_k=!b~dga)^hSuUs zSFTRp%zR=O^s){rZZpQs1%tG@P9IPhq?x?n&&I*(*gIdploZLQ>C+8^9q*t;QEsJW zQJ6=s$#tOWg;#Q|%C8eJpU+fEIjfMLDbAKqKl&S4vH zL3x1^ba=i;q3M`UD!tGV_TVnnkn@*J92!lk7z;k|_*-(XF5sb*Y)(<>`-U|i*r#Ix zTq9`TVM7|ob!u4#R+*UHlE|sFqW-jFWH7T&_dCmV4VVBPOje2RZa_t8MD)lPt!|E> zW-l9(Q-!7RqJuIENX}gRpZX7`>#XRMHEdOpXG6zU@{8$0g*ra<__ku$$<(b})G^JP zh(%_)4|Y6{@puf>b6*Fy?Pb9R!_t1c+XTkHqMV;7a+u2X10>>Bm4s$GX?_xiukr_y z>BeSmYJ~S@N{9mjkUB2<)FBP9lE^ZdKgQDNOH}@F=h72^>*&alWf~c6tPRfhS;MZP zirZb`lN|@@2<+Mk{>T?hEWIN@O%p8eVp>5zP3Du+^^k11b&14|B8a1LYa=SGxWFeG zl;*?^8;pumFkZ$PhCOmK%>U69w1^8wY(;n*Ef#{^pKb-}@A1(gyMyNk!UZ65avqgm zs38V^LkAiK!1}$peiG$$YE^_{XFG}i^zKJdE7$Q*=GOjZ18J&Io?_DX{jV+L7{U+ulNdBg*#L94~a z9A-iJT`-Eee?n^#hwY;Jk*>s=q$W!38%F{Rz0(&ROz-L z#%jkPUi(SPf+4Vt&Y%~3ir>;N8@#n&n+m$$7e$r5py%n*>lB7vWRGtdv*L@31sz(( z4N1B+N=TVg0au*wivlqYCEsx0H+e=s(sJLeO9Y#5v#_IFm|HcCGV~6@e}gz!&tFRU zSp(7W)Gm=>AB11ZS4^k0rgl)26a0B6NaYUACQ+OResGNtz$ZFXiQa`&hpj#%VWC4^ zph_7hOmRnTD3VuuTn*=3V-y`wiG;7kW?Z|*{tO9qIc{CG1S{TTk^A;y6p&s14$u=- zte!5rqZ&%bVX6UyHZC6H_tfWN*83-D8J?jQaNZTWCR4kw<-tHMPUt9txc-))UHY_m z&skqINKF!K*eO2Pt@Q`@)u`IchSw?3L}~F(7JDDeDJjgxoi}^?FwTF*@mywj)S0`n61nT(DW=pu3jsNgu+Ys|y z*inglU1Yv+1$J*QzUw(-9(aGTK2xMGNxEX2E!&TO)B8K+iE@E=B;BdOTbJmg#%;7L zfjrdLnzG-Uf8GETHT7f{R7xl)5h!R7uKn!az_GJxxgEVmrS2p`_P#$#giXTLP@l!B z(Ch^hnjUF}^(GCG((f*`_a*%Z*=?HHo6sAmll3)#_>`Xb+WI$_H5ZUt7RWp=nukqTA?|8UA_x&SUn9W_GjEAQ{ zjCCk=4dv!x(XT|zo6!qj_4p)|-U%N>C9yg2&aAmstXxSzk6M!Hz@_!o*jUABubm?Y zYTp=DiL#>X!@nQ@^lTKHcr9VRva(8zjeMfaVke=Ik^!7%-{yHBe%kBJ$r;sQUTA)U z>sY>zgr%24)4Kb_etZ?5X@%vU#L;pDI~L;l0( zNZ*K<@684ekS@H3}8AlbW{qb}xEA<)~X^kDU5o>ggG*R}rZSNqnI zMXi9`^j6+KHy7+{lh5w5&61FA>PkUBLVF3RR2{CDYvlX}+jXB8k+C4s0> z4_~-D^yaT1_&=3P>6Z-7SC*{Z$JC)$@#8T)$Yj4+G1bV5>nyk*K6xS1+pYshx(mP0LNl<;{)+sx*AMqwg-Yy8x-{Sjj@%z=mdSjp`|jUp6leu}#&A4UuYwU92~X6I~nBn(&2jbF;%$YzL~F z*yeZj5o1tAqdrei4zrnSZAXylpK5;$t+IC^BjETu-t_Zqx=qm)xsPY>l4|x(=7vR6 z4^fXD(|Vsgv*@@suIjDtH9w2X)9@CyRPxIAY&h%4+;fvj`YdKGk?$8zDUdoEW0F5>*Idf04*pK<PgO7 z(}F(1KpchnQ)(8##tdu7^r9v7!xpg0-Xaf^-cjdwVUQ#4BbWFB@!P@CWOhxWJ)VZD zg(E*Z!s0{>GQti|1|PUCtm#ZN>!vhvirqP7Zx6UNxP~8k!RLo((=($V<4Iurw-e3y zZ>@EdnPyK?7@vRYo2kSS+WASS8IxZNLq|i4g$BVL$k5m_=4))xQ`GpOMUEJ8{mR@Q zt>GNw4!Nn?{JbsPFL^!BpI0oqmvcgK=BWlby0{FJoqGPAx)WCs`Ce6q_jXUOJ4>Vd z&nKC4!0Qw=uOu4Q($%Z_rQB1y0Me4R4{>=Rw)y76<-CZ<)w~ECtB)L%=KF(g$*VkLBv7%h{#o`K8x`$5Wbq^rDt+m(QEuoNs7= z1KVy?w=wXz%_+g&;*I7JVLG6N+Vrwc>oZ`(-=Yr3SV;4ZX#EsrBOtJxzI`_4Ur)*t z9?x|0l8ySxYb;C0g!(g=Zd;ZOaEsrtCC@a^ckwOs{E#GJwgkqY!P#n-g%23^e)*=E zSN^{W2rsq$|5fw<`0#d&pD_Kor1X;;e)zMd=*Yrly9aEI3AOP5BH?Xgy`J`oUVh%l7e4yS$``p7w~aNjCl)E5qWk$ zMDN;t?xruDHFztIUkzRaz21uP!j*(tJmbG33;6}KmNnLrR**+`+pHhG&an-I4xI;h z+*0&!7WO2t9se$^xW(T_y5lmku(ExaHgs;n+KEGEmz1&EK7(gD7qoWX^7GI(w(@*b z3V8kQS5r`fM>j@ix?sSP4GhRwdG8mQp^?nt12vpzo;!4qJ2xoKpkJps!JJ-u6}McH zRgB^$xE0+J`~54cc`JCV|FG7l^0u5TczCJA^D1r@nhR--FBoxFbYh218*vxh&z9c| zpb;WKiQJA$VE3!$TaC=K<*`4VPWKs(#S$t~pBi1U(Pt7IS)uDDXSEZ_n%iHKV(|an z!f!&WyqSLLC!OdR!|jLk{wm;0QJC@uQaav2!Z=c`aiR=6r)hQlZ-jm}KS-ryH zoFn;=7NFGA8f>-ez-9v|6r*^Tu*%UI`nfSK-vp8^ag6~o?&UrppXrYiXk5LrlyvM( z2pQUuG%fS@@zs~+t=LU90@yV;(tXm{N=xVR-Ye4=RmERv5A`u_;R`$asi#$C-s{@S ztg9?|GRj-m+mmY3CmVurQ`VTq1Wf5=v|J>@@Rv z6H|=Wz2|1Yw7<=Wx&z!ps`lL?ltHLagA8Wq5ee^1k~{mja3Y9LrU!^RDN+N!vyMM* zvPr*sL2{vB(w+AGNBJc0OMF1j;qTQCvr&}O$E)|vPp3aFn8@J+9!jld8r+yPwD?%n z@F+NVjB#oyg~mVsmP+3{7kl%m`qiuGHk#mV%ushgD*thu7SBu7nMXPW;cXKI#V35QB-GzvckTCd+$H!xzgARKgr}BCiA9geg}+=< z(_G(5Il5}JdX@=sCxunf=Mh#g#)PpzQI^us_0KNh+aC5H>S~2`OAAOh*7h`ZaK!F6^5Fp%ni&^`&GpaT7ZCFiC1UvI$t|yUfjr` ze)Erh__M~^J)b1x`%No{EH1yfc>6YU<~|}MQ||r%DJLEVb5Qn}R%;_DfJvEON12cz z#yDW~DIN*SBy{L2hW*Gi{Uw(fwPP>A(N&WBgovPu*1NK?HqlG-plA1@ zukoxf@$cA3B{NG4xe5m30H-Ni(Y`vH#fQhBiRfg+%!_b{bVg4^nXYtRyoLl>%1}a~ zR&i&g3JX~YcYIUITs4`wIC^5$iE~@;1b)##N&=4ghfLky9cdl|O5?=%`E2oNtyb!X z=@MH2Bzqqd$M#A1PrUFfdBDhXK|0f5nY{^au~2lO6w1&TPw{qJwVq}!-R8bqlZTt5 zo2#3%o4cFSvmR7+b+vuH zO_q&1=L+ZXE4nL&>~xmGQ%yV&F4f~W$)D!_ejh_`VQ+HJvCkI%v|q6pJVH5}i2*#H zvWJyZ%iV74VfXl;(-oVE?znD&*N2nUj!UHXQskK$AJRW~BOTiXc)Iqu{BOi(HvH{{h;B6v&ph2AY2Ve9aYpKaHROP$a- zf8#X@a>xGLWo-LRPlA~Up?n9oZy6H??aBtRwJiYsu zB!YcS2|!1?d`0e1N9ev5eQXHy+x^1#S_!MtGt^pgbO&I@OeO-jxg1*=u~ih<%)%so zs1`-{hTv?9RAP7Uh)#*a6!eg1Vmbtvw*(0xm?B7rl{M`7k!|cS&;oJ;+OfZQV?A)M z&)65z7Vfbb-dhuhpMD5nG9uo)^=c`-vZA4(k!Adnd4J}ao~{#LByYx)u4SHeWLLqf zM4^-``lmEt-9trb5Pk01tJ6ccVmq+m8CWNd@+Z>U<``x&MQ|>UaKFCNVmHtnz-)`| zZej9Fb86c3M(KoAyI2mUYvMRcO*vr=WZPV|}nBRtz|AP-EvK{}AxbkY6kQ+TP zf11X&EIJub-dpxaVO!O5mfbuktivgH$|TcVn-RAZ1EY2ur3d6>VdAPZY{~t8`rYc= zi`AAF;Y(X=JnNF$5ez~s7|nqt!%9yE(Q7kV@snbl10cWgc?syzXM$IRbnUZ{fr}dM zx&XwQ!PK6wU1s;@FygAxLU*9S(Q7w5PNb0EA7XDOO#DM5gAF^%noinOnpWIeNP(kA z=Tk4*G8Dm28qO1_zn9p{D@ebpOI(7vkd5=) zeC$N`cU?P{kksU_Yh!!TgoF3XfL!K02k()z4X0<4Ijql-Y@-j#4`uJ5WwP9j<-0$0 z@3*PSf~x74H8ETzn;u?W0kU05nTKqAi2}B$3`Xt@(xOTC1AnJssCs07ens43q|Ok$ zRyA~c7VJQc^ClwN*Hwy1o_qJUz!826*BTIPnff07fYSlzkN<5l2^eSH3)v?IRut4Y zBQ4JEi;b!x*m(~{`HnpQ4vCh1oH2`(w%5Yl89a`hQlGE46SVS&Dg1I*;&?5cyy4R&AD zK4JUyI}$@u>;=4Igj2X-Wmh`@v6|VNjH>puCDn1q=bL-)IN=d&24w=0AE3Nv=wxy$ zymke>;9A5;)fml6nYpLd*UHEtahost(w0gIC(AffwD*DbOc#@v`je%Cgpl$tfdyXZ zhg&E6-QNKaHpH_8R^~WwxZUhVqek*P0@EYVv4jN45PDViHjvUUL+3pN%YB#KujPax z0m=En+zvz}aoN>-0U-%-uq_ZH%jk}4@fWIut}-yKSdTXq2U5~|R!~b6f_!=WXU}hT zit-`29W9R)x-MABW@)L8N2lJZ+S0vOzC=XyXzlR`6|CSNz1GXVw&^HC$R>;Pxe$WP z2gb^E)xEm}CST~nrBYsEVM3-GyAa!BsSq0uws5#@~%yj`75LG5eEvI{t(CRH238$?}llU4{U5mt7}ZJ2id++vnRGPjA_iX~xSu z!8*gGZjkAP!?L~muEBiEzQld9iVNmXRmB>`=T;AoJk%;vPogZp=Mc%?(5) zk%M4qUFM%3w{>EWJ$(6MOmTmDgAHEDz0rM-!_y!=Ii$JaT-IzO6}A4EH@XKsal*Wx zXgByv3Ix|j#Ql5;+gimYJRq9J?g;ei!aoQs^1>H0tDUp`t5mB=b}%L!q~^wn`i;o~ z=IrOVIsTYYgL><}Y<(u_6Dk*5b7t6}k1fnJE|4~iJx+pTg`$yr`;w`FL&2&gcaCVL{zC_)c?>=pvwr$%sPusR_+kM)$ZQHiH|83j0=1k_xy^}XL zllf3P^sinKEqQh5rn4wjj9<_m_3D~$PE#S%c|K?0$3XqA7|_>HF>cYp znW}=(kI7XJ)MsE2$RiBUV>_)d4)#pcscjL2s2-ZYVsW`u0ReW$Y4H(v< zBW=hTaQGAAcXt?dHfsPKDF2e@CQ~u;FD>{u~h6H>duO*gr`ny@AwRC3GG}& z2u^tYJ&W$1L+*%VrDzz~x$BN;#X1ZwT#ZT~SP5ChX9gG`oyWv|mC5pN9*$afm<}QX zEQO1v3t1{CuNJI^*P$NR$MKu?%EM?9@U);y=u|JGG?&8tEaOiyOd?-HNGndr!AJ~YCDlfj2>slew9YbP*f6;Ru7F!MWP=G(T}EKy zDon?U^Xrf?%T*S7u~$L*5TZ$+n!}MsDxY%0E|1TU&A+Y~@%J?hzm{Ox;z68{;IrAt zJkOO_Zsc-ASBa)HXrD|+mAf@;pl4MAWGw5??$S4SK7~&G>TxxiZ06b4F~%lfreNdGF(A-K>y9S#RB$sf9xaA@Ol0d9RnB6` zEQC%W#tL9#Iw`4mEtU~^NW1>*nFdWF`q?c?w_-n#xmHlLMS?17_ zB1P!M)BJnHMR$l@^&!$e~>reQ=Z1lRM}W%sC2OMQqsolBKbH?Y;&MhzVjmfZ4xD7}EYUT$4>95FuaFY!my6mBDdH_JQ3TbqTPl zA5E4HryV2k7^JYC6JlF%Cnvkt{az@?fiC+1Yw;ZKH~%n5@*EOfOg}{;TZiqa+c5JQ zT1O{CloM%lQbhl+%wV-&BOR|~v{!5puVSA2PH{&VV~Z}ywT`wmbz5~YS%1&!lvFeH zp&R65OQ+M4lvdD;)WAP*n*#-CBq*roK8ndIyK{mSp?ow1YRJd z8^8hF7-1;pykMx#YP$cL)vU)`m^oc-hEp+I3BEN)kYY-~7-pP?ud9tA*dyrLz!y=& z;JG9EdnP{i7jOPXmMP3az6H~Y*I#ADsT#7<6nVC}ShY%4Die58wz0o)NYDl*!?f(O zJUdFl`tlc=@O4k1>{C;%dQeH!J=9*Pc=7W{nz7&h~Ht)dynVUS;kKkAc# z6`1AoXo4b*f#NMiZ8Y`-!V5qc+eRJ8=J+$r`Buedcy{ZI_t;WT+p_ZT*HLxl95V@F zX2wY}*j_>A0Ki&INZ`Qbmz9$!ygt8<96fDAk*Y$^({Dph*{}~%;fFZI8xL4}R3WQY z!{Z&szXIW}IrYK^o_8PxUIUX>y)ey z=IuAtcPgkLJ0sptf+1Xl3tmI~|N5B^IUp#3{$nByD!N)&`e3Kr|4HsBG8A{lz zERN^=6O6Ey!OlA1y^^|ptZLiHOp%eir0|z~D=`ixm5DuRXQ3wp6aea-d`*@A%^K|Mqv0FWKlE(02DM;SNi^02 zRoapc_DY3Q;nD_#6s6JY#jv@%=AcJ1yk)$Xci$vW@4xjd4c2+Fz9EI6L3sYG>q;HM zdT5&&H5Z512jY0vS>eAO8(rWaQ_> zn?hAne-8C58=50Z(dGuT%NEE7=?hHGmGl^{D<-7nfURcdNiejyECk=^5W1RkxJVFA zYpG!$PIdHw?Hx{1gy4gQARU@?&KXroS_tWdTk6B~UM={mF>w!DTYBH{OEK*=rT9YK zo1Lgb&U(*1a>1Zb8BnJ+{`7*OOldWw}i!i8&+_Q8|eH`;HTO7qoBGL@Y$b5751J?AI6U!UU*2v^QtP zdEKZ?#$I8v?a~>E-dGho8rf*Xwu>!vB+AM5>JR805%Izl<(Sy9IGCrk{GdtEbJC1f z@r@xd;IAGY(zF#N9xn5f$J*QgP!4pIolZpJ_Ry~}aTRo(D?CF}=mP2q1JtUG%m!Fm zgk>*&-LD{{FwwB*I(cb{T_uV#wNmn+ILh5MTN7RMK!q@^fivy(^=CcvY4|l|+<0;L zDf~)975KXgz*jPMBKD|*YJ;-924;J^cgI)-mjr1@j#&23gz^MwZcEhf8V>`ar--J{yUS?-LUWovObqnWc9V9JsiyH$Oo8E8}*)p{Ofmh zDHLosZvULy+)w|hD+*gagzR4wvDt()CVZuDJKiw}EAd-WF#9ZcS`(Fe)h!hc3yj7* z2yh-E>}9#+ye!~y4%6yJK4OTU=+h=BNyrKp@u+B&;j$pFm@<0upa*&V@?`mv1QfL^ zMH95=3~1&yp$6mnhWqF;FP#P}S#LU_{KxL9=k-KCx5U3|3-|m2!~3LJJt+sx>yGKd zQZKHGIY6XsOO>>Gh(DW0UlDINFy6N%bxR-#uH(bAztiD4nAPQE+vhaDvfzAZ`0SyOb zMJl{x(d{HymN#+TQ&6`y;#%qdO+db^N8lnN0w2ILW(or0OIoR?jaR-^LF8G~%v4Ys z+?Md?ElqP?1I_8v8yIrcUs?lVKIU154dntirl4{Otf=w*DsEs!*?Ub^6$OD_Pegqq zeq8D}yt~-MF=d3U>D8-54`4>xk)TOF7WldkI}m7>6nr+jJiJ#8NslO)IKABM_QE7hoRZfV4rL z^u@kB%|vs@*{brI)F zh1d;l!3+1&@}F^EjH~Pz30rW4oLarM;glHId1+P=1_L&!9l;bz=+hK)UcVI`u?OAQ z8#&kgW$;(nrgSEeIyx*_iKbks1)B-%9z~}wWPW%L8gll5P8g(*BP)()LR@0`U_$a- zy<06mxRMu7FgYkrI?Z)2K!JOriy>NxK7CX7DAH~1VF?Ev2=RQ_Y6ABw6ZPM(vx+rq z2w)m(E;}@svpG~HjVsMTfN2dn1zK>=H8eMC7-G^uFRi;3kkm-=_vYe|3$tgBGXjnL zc_Eu4$}>Qy9lH5aKtX%*b1?LEkbII3wGYjs)CC9mXzl2bo^uiwJu$UN5e)HGQgYqA z7K5e(j;r}*#^mW6W6obHA5QEnaVAP~i)2 z%wuSbX~>#RDa~3b+#;?CL1(gc!66&ON%@aJw=iWyLR!h&F z!z$i6q;|>U7p+!@%UXLad`SZo-EfHvlN<#m^1@)xGg$RG2eeSjGKdBkvm?y1mSI#V zj^|@!@k-($-PE;Ot&&I=QLGv1k(t3zrO^7)3=P;YStd=o#gOF_z7Q_vwN(kxD&x_2 zAsmuVs+VnD5eSFo8PmXqIA#zkrR`Hbub@r~=K36p06+4NapEH-?;;%QCDUd=wMv!j zu~`coqU&up#AlMz)SXp&l@n_w&H0y_)><6V7?=mxoV;1WRkT{bm9Rjz`hZ(+{t$6M z|K|DdeL`l{xq}AxKf>vFCr~imekZwiz@rCFr(ft`gi~A18nT%dAt~`ybSuM9b;adW z&{00?Ffg~&toLq~kxv0bLY%1n8!(9!7c>6q*Zq0ca$ho;Dgi=N9cdfas6$bGxZSE{ z2Cdb=wI!)4H6p|3x+_^U|`b!PYz2_eZ3t2pcoY{p~kCcTN(SAi&Fi=_}T74m) zf?uKZUA?b{9tiM>Z405(mtAiJf-7%vU#R;?QZj9OQ|!SJ$h`q3t6xb}I1TJX(J^*& zQ#w!L;A!k7TW8q3+X9w8f|kg8c3vFP4EuFm6FAK_$4s99g$xh@w_po>0g9Qi9Pc>#XHh?@4*=itWW@8c+D`H z0OSL-E zI31iwo|g8%G@(;Q!%CnRa@>JV`;-GB4deQ$?-mYI;9w%PCo=E9P>5#t$q!Q`Woi}F z2o|d36&J-Tl*UcJ)cSN4#6dTQmqzvLw)#qdgq?#k9#GE)5CwM=X!Vp43;xj_jhCZg z_84-;^%)i+V{z|i6a$Y`I{SmH8UV=J%sMloaLRGjlMYL;$oI#vA-svnv!_u(93xzy zQPE{r=H9UNi1zoMMTPmz-q5Y8%W12WsK&C{oe7p{@Fl*vGo+e9o@Y4(dgoVkGQ{4` zz0dQrVLFAPuijRETZ6Bkv(alx?WA&FAbE)l5I>%$D}?X!wZgD@dSPw4ppd^2U-5r3 zhv6Y(3iKeLrs*MLP>~^JkrJU~i}k{s8ZfRYUPpgI|3N1YAAc5Oog$Zqa&yB2cC0=` zHvd@RB)<7}VkEMPe+K64e0BH8{q32768cCz!KZnV%Kgd~eH71)!H>kjs^p(`%WNa? z%{Y^G2RJ)m=O}#uozL3Dgq?MYzv3E&jM(7CCoabvf*yE^0Dgd_5;!&glck6GzgT*t zO>E7a%^3+8IT<-Ppy|adtes693FyVF4V+CxOpNS|O`z%j&m00~Hf9cJK0atCXGaqQ z8))~eD{UWT-f8O4~wv2;KV*>U! zEXJWE>0-sbL0ocwc`xjSerbOc=UqS^Nm^)Ju=^m=&-&kcL6*~*nv#=AFpbqBIA#XM z3CpPtkY#U?9sYh=6x8h@Bc%4&XDPOc1G*Ik?(Wb>Wf6o>bkD1nOpAtjz`94|OP+~4@{`tW+w3M?ixZq3>H z_a_a{R5|bpesk?YmPAM}CrOt7j6a%i$wS!(vV}`scWB`u>=OOx92r#lXH4dlsKFw4 zDT-;EAcNV75`XplaZ#OYEo=go9QzRm&2iz^5c>cs_D>>was6b_k^n0+xmU%W_P++! zvbVt`+5ir3I(ACGoO=e!@rU-`fxm&F0?+!z0(@VMa1VGN1X$7MVa1tLoAt119>o9l zAl9d@#5UwMHt!Nek|c>2`F|RUesm1&yfkWzr~F2@ds~gFPpU8=Fu*xLNNJKhlp)ku z6NF`<%ONsCz2}Kgf`t?~{)&{Fvo7RoCzT3O6*wwKU)+dG#65tww-cZTrW8OX0Xbrt z#|&*BET@>wU$UbrPN{8n?smJyeVCte9w2@)1Cm_I0;Qq-s0yJ z4P!)+H2>Fd|3gUa&+7*?`;A904r%a=t>6gbRey6^Css1FMTY!bU;|m`19>MkuJasS zEVWlO_fDXPkAKC|>{zfQc5zU6cbtt=%%(^=LmDRCK6-~?qo^-xFg4n-)Ci^H{`$A* zOsrdXCyLk9#@FgBh5dM%|K@1xE9@11W%diHD)o8i(5L_1*nDMeZ9HC0R=LwMJDYV| z2wSR}mAQ#=rp1uI+lT+j(sDw)(h?qjTTP|e=%>bp8f)?X8(}Gew0IMArO}J8y*g*9 zAiJgYa{1pWcn!|CL~{JZ$xgm8KWxNjD-}L1!{ALwfCpGTI+S6(*kyV)@->x9ttDyz7}O_Exm3lK$7#YP(k3YWFa{yjXJr3r4>b zy=PNO$^1rVEdbfF@1x)uu=u}j=m55Sas&_h@K1FNwQ^-j@dgFRs!on_!gUe03E+&! zqi!K9!&A8RV6%feM%MiP_pxJUvy4J`aEqtG!jCQzV^l|KCm%}29!lAO#0M7>*-myWR<3ho0+wiW2%t^M< z1mlNU&Gb{l?lp80rM#cLxu3hAnjfZO)&4Mgt1W>a>DgUQcW-Ta$4pHHbDeU@&}+`+bS^CP5%4~jPkOjjOXu!C$8u_7$}P zwI`7RJs^ip0=mEMvBXj_=BL1@5T-u z1xdU8qzzd%6729h|7gqTIThmT1sz2@=8x9T9qf&PNkyp)VwS{TfZ1`|incLXvaZxZdCYyPm0&>tj&UI5Vz)JBMlwc|hRe=Vz2y-SJBgfvO{T-QuRlHZ13#78G&zdZLj#humKbTqx%y71*}@-+^{o7 zg~4BNz!g9@zXYI7r_9sEz;mFk>#pKZ*T}}Qlq;z+JZgch&Gt{sPb zItw+aZG+}m8dZ_~@T9r$2dCh+8i7Nfa}8%yuX)+Wh4bdiJ2sh9Dhn95lX^BYn{JTo zEU!O3w_6WBJ3K=hRQr5UlAL(mg`5JkqV)u%Q*bJzFIl6EJ2kQ z_ea~PRaZ)Lu1!mb>!A-oa!T+mF&fOjnb;DSYU)xg+qyR*Tf3jvTlTMxGnIT(9Iq>{ z0Yy^qK>_Z%SC>q>Z%v8Tns{)3j(&H`WEK)l^id4uL0wkn*~x7sgL6$(2Kx16WtgL@ z8u)6csLKz_`8r*?`+WAa`(9tWbGd@%e19e>IhlF;)?bDG(A;w4Uvdc`7lQU0w9&*j zNPC)Hp7OZQ*i*xS$4(Rhu5+BmRh$o>_xEwR|3Q9g@3toD??@UvEm`EjBVc1sy5G*1WRk;+`lU5@P=-Fw%hL3EJ>>`NG^1k0W_ZH5<@$+D99B@9$O|wGmY|syZABRyt22?YUqrs71XfIQ(`ajfMMdY`I zqhXXGcH)0_FV#D0SQ@sECtA_NGvgq26-9c4^`|o%KZgSqWfEZ}Ae*l$6D0%F-cQc|5B#y)KU z54v+aG*etH)C24O!v@4k&usgdxr?G0zsppLqZP%K_-sq5rvr?25woWsD+KM*oCD|Z z9+9yEoBQ`gp$%1?oqygzJmK_4z4Uxdev%hA3$yd$hjU;FgpdV=)j60T>qzB=nX$<8 z6S{aET!SG2NPQ)B(h5Phs>%0=qn`Twfa-)^Zx^~^q#fFNnx_ONr$}dY4-u5F@aMjX ze<+!k>PlR^#)bS@t$r>ZWc{ZXuFCXUC@Y*L}s`byXz27&Ev_i`hGesnDZMec#`1bmIJk7p<%a!!?D3 z_m@b#f&ym~8&yy?P*bQ1wQt8 z6(UE;W=`s*6&Pm5z1OQv;{hu-5e?u8IEm%gc-V~l_>AiUjTY3?d{9g~L75g`lL)(? z<7&bxE?{ZGD1^MG#~HsVag=avrApaH?y7P6O8!UhY-edS^gaT&)`&V?8Zh{Va0o9e7V7hM7pJkK| zV$ToA*i|0mGl_5~WW+mA zD=67fVrB7qTd`peoIf*Gb-(ZcGJdKwV$+5F5$@3&;vq>^XYH=14w+-|keCF90R6SH z*~bv%yTn!82E6tFoLL12JzXq8$f;3Jb7LV9B-(Q;nQ;9O8`VkTgv4+#wEbI@kLr}s z+Ss*)^x&@j)L`?L5ixNQ&L%C~{+`;nF2nkM%LE2s51V>E7B++F4t(3*(~ze^377+9 zV&dP~AL6+8@O|GE!Qn2F#+Z9wMs?RsR78ZHx5TwR!K>m18yQ7IhpgF{#)vaNq&MW= zHY`eP!!VC{g_;adDVw|4Iuz zmRo9>!jPgt%^}I=wKr_Dz~K4`kKG*qB=Y0z{Ow|t(2%f^=!|zvZuwQrE0<3E z)jLTT6sH|G@#ZcnMyuHBty`-!a(_csByVC3jbHhQN@0^D5hB62W%ZHR-noNwfmwuA z#1dlZ*&R!Ha2>ChAYds$S5DMkmyjkw2AFe{AUJQ*MI)zR!6=7c_|bV%6S|` zW4(@Hz9Zus$^}jIFs9THROIG{ir?U^^Fc}%6sqG59CC4WZTal^3>bF)(ioq`DF%qA ztcl{JHVT=mali}0o~ldmK|5?F#(l;+OEAX;Cf9F@9TQ^4rBJb8QvR|4TTm|IC{ixU zGhz%LUkODS_yNv`O$q<(^R3G{?Xadc^ZH-piNghGQtv(w6I zaW~|gTUcQlb1XhWoAlGj5uQR30xgWIVanfTAPNv8M<@J}I6zF6WKwXGT?MY@c;&_z ze}eIh{;fG}iZPC5A7;o!9=Y8BdI_9e*E8YWt7-C13ar(@r8Ok5EWD7)VJ|aiPX9&W z#jVvmv$i~vZuzctA+BNduEhRUo~V^)QnHe^tHEbvYJ7BZbYwRw~u1K)EA391J~|4=H%NLojfw`F`dZ^9n4LI~*h?#c%2igtB(!4~Sc%viz%q5nch zYzxtZqkIhKJVJqG5P3tj)qb>CxPL%o&$|gMVr#0C!;#EeAs~X$)ilH4srFs6f4>xb*p#Zvb#~}{FxUhVoPeRN zM0DCN?(cxRu(ikEXHw-@}5+%<9QiN2t-Lr|g}5~YcOf$H}= z&pSNNXiJ?)%5(y*!?xgMlzM^Gh=;h7p8}aE-0CT;x0G7YrSNYiJR+;{$qitytPU!G z>;41w!9Eky{yv-S)^!4A!_P$WSAS+0-q!qxtq_p9*YHOd594&|Kc=HTZj_aE>3S5e z7Zcmn+Mq4DY}WhY*&_d2bZ%QK^jCR8wtjhw>lz3|p9!o+=AIMa8P0GB4h4QvHKYeD zP}S9|Ide8rP>MWaAl}t&%+P{|DV2D~^00Bp{Bo!;+E7&J<=?j* z^Bb)p$h^7ky?mc7CVk*!{{kMRq}c>}nqppCru|?G^LMq8CIFG@l&uJt=W+ z1x#voOL-1kMxinpDIm=7$MdpvpM!yp$U3QNKE%*7k3gtbsj51SmoK7#_H5DBEjjZ| zyuaj2)9v&2VjHB%0FKYuLtxiJhTI^9l}ag0w`=v9PWN)|K_WGfyIy@f0JLKfCln!5 zcSp$9Rno!L)j{$(nLJ_Xd5DHLzj_y*zV2ooihA{h0pU}FY9suN7NWs`cw@}O=|eJ} zcD^K)KOZ}SXHY*cERb7kXFGHD*ItloURC443|MmMl6+FKiu$(W!Ex(?V3J~=oG-<2 z=n3DH>~A(M;AxQ=WJjX&cW*;TTXMs@XG zzlfwtCLf>nQxqM7t(_)LVzs*wprrsUx2hAt>HfW!h`H%$RN_tfDEooJ;ba4_BPeb) z-S0GB*4kGhx;I1XdPWoR&*H_~)Z;lSm9^peg9cUck#q2x5q8~im$uw+>CnMN{@VMZ zS;3ADG=SEVlO{fwU3N?EG8lgE_((E!lv2st!rg#vqsl-+fYE3)Hn+V)*PLn0*Y(s; zeNT@O`BH&5i;shw+K9tmJ<=l!S_)eOX6#y&Sm6Zj)nw78-Jy>_<`N;QI0TJB)kXc^VZ*W-n6Z`c_Euv37dw&Ww7X_b=fvBy4UT4I%rw1QQoSto3b% z%ZqW+ZSd=N-ZK$9`>&_nessCYk((bc%g<|Kc@56zujm_Jz}*A#sy4>+T|t`C!-M5$ zCzrz4dC_SRHF+4A6y}k_pV_4BcjK|+C*4Bo%}pU8F;vG5o*<`LwT=DFpxkL=f>MvS zzLWFNQpD~$YI3WG6xz&2$D))yFGIRb+v-@V=d!ZA9JSgV2A{iSmkv5(zR+xlOS;Nz zc5?iX{R%7j9+;Xdcw+AtA<}pQB_VS-VCv!H_JCL@E1CEzw8~rjb89ay*I0> zs;jH23MW5a_U%abJIjLs?NR__`$2uDa;5iu!1;hn;c!-b)3w2yyE<^G#tW_tJF?~r z;UrV5B6jMB!$5SJ2+&^>v^ZEPM>T}YsS)$~Tilq$WP!tCMRyUgY`J8<(* zmCp?=DG3d=T3M4}W`@Ue-ZXMwQ<#J^i0ntF=|l1sM!!BC;g{%-t?Miqh41zjX+nok zsnO1kS5siT*T3%!J9VJ+$Mdt=h;S>mZmxDF;JHWB1Ku_tE~hx)e7oF8v;uGz6 z=p)lRk~a-RX8paQQ&K*0I-8^OPWzJ7E)#IQLU>NnZ@y*G&gXsU}b`N>Ls z$cq=F!X!UwL&IV-PgkntvQFIIn?C#=DMRrO&x`KAOggOLc_N>)KFAbBIT1%U#7{D>NMDBT0RA^K)qUjB#?T>v5LW9hN zMm8p-FHQKidf}9zVQV^jMBI86N-vaY%(2-%YFc^MR)aBf%p|;dE>5V|O=~#6TJ04EZz7_|m<;i7> z(ju{D0`_0gLbyXy_2u7TvBc-+Q{}Z@P#3)4??+|}sEnT@>&_?nZNy|trC9Ah1jH3y zW+HOu6*zApk&RL())HFYL@E*RlNLW8$4@XYlcKrsJUphe>42KUA3y&B^o)o!T9uEEOaHK7vngd^qr9k)kYbiiONRTg zy!BB&$~dW?ma4k0oKW<>;OjPS3D^Usjt0`vHDod!E2{kjHkva=k?grzfK{8xW&A02%}FEVSNvKcNq(< zla?`!&xJSm+<#%M&Wy{Y#;z!e85N=K!HD$G?(={6#9cPM+TkM&Xb`ES-P0;q1i}7% z!iEN9V$f}+Q0>BIN|Y`F)BJWN@}pTd0l(KGhHM5qI@9aP^>SjwIN;HZc79%MXrnNA z-d9_z!h#G|vm#(C&ftB5gQkMwrUp-s40i7c^b}dp(=N$c2?!&YYk?##f@4|q{%b15 zJ!}Fot#`!)?Or;dG$Hi;CnLO2GWk;r?FYPzT7_~4Mb1-?dPk_%wSJ`)`etc|ddITK zN30}HBtZm_xH1OakTsOR%JEK$6cN7_5k*9AG=H$dgtI3?c96zOf_cV@Btyg?1UIVc z*8n~0wYx%1f)|MlbrzpYvr=$}8_iRDzzi+^OsI5cMJfeJO36WlG%A*tbaXF4{&{?# zEk8l!O}3Y2Lg5A$<0SMglEp4`{ZXC8*?>Z4Ko+AJ@-O>~A2Q(2<;QGCGD$B)2+48h zAKaPVn%;QoWI6K&Vf_*Bl|$AzXlhi#qkQpW>!}Lpt@UQA@|(r>^i3qWuU3!qLsT&U zj)JG(bz(px;94RZYxBnlr{^O#0v^H$pCxDr?)w3j`e&h z>9$m*hMR15#^Q1V?om?BOMY^ zgm+9JEnVwqqxXwVPbqRlWW0^pUvegCD3rX(+Tc)~RYxBwv$4uB%PekmI#+JE-Taz2 z%6KoF$$rSb`IvdrJ>fp#ZY?V+f~;4Ef^l@zp?iy8+yMu!On#S6tt_fD-f)ufXMyO8 z`|PryYYDO;>WDve5WQx^bcqmO2TBop{0#Ax!*#pY?rTUn&uj%GH|4z&)ZY2cf$8&fNcOcBmAU!qaTd>E5zwBTGb?H&PJ2L zF$h#Z#37E<;&y;`-`tJeN)!TjK4OD0>)7GIov`-rZTNH1guv@66N>7g86+Q3j zeQu}tUWfSHRq1nNbwXhT7fwm1WYA!z;cnA-jOhG5DGm$6UYkWIC9aa~k=6PQrAd2Y z0VoE*(aq{2Ou9;{gp@|G`=&~I;F8#EjX(PA1>)DsBtL>`B1GBV_%_dYH$Txaisyow zh!H{~_EQ8iNCjT*h}h*z%#1VIgg=Ao)57}4SPabOF{&tYtGTjNr8uTWWM{XEzlA$w zKOuEc^Pl8=KYabJi8P;X$|0gU?@vbbkMyJ99KpJETg5eaSa&O_Gtx1*YE=aXuPb$l~BNP3P&XOWgl0_vDew&i`~G5H2Ni(DOS1jbVql@^&t#|NE2T>kiMpT}jzr=-Li_SKV3vFwQ; zn_@EX%CLPVZUvmn2a%s9>jZcfPaqSSl*dEeYqM#mcKX~vg%KHBVWi=*3Os_+6s{+P zYoIV+MJ3z*&A!eGHh&a`T^`_AzjN=f0g3k)nFtKB-O$$#j&y*c8%BT~X5et3bz}%> zNRQ-MS3$q0R9o5e-1I-A7>Z8XG29d(ABskrP@ z7GCux_S=-WCFv(3)<4zC$S^ZH$217GekS!rnnH)?+NmiLHKr+mOFv;5j>7xc?5$FA z;?Fdrgw^60f@D6M;6E%yJ(MLDCpK28?6m0ABI9^F7VACYn(J(m+`Ub-b{&l##gGvu znUt8=02`ehs_p_j?^s#Q6-e=$NoeQKh3|OAp2xk*TA~|=4M8WemQEndWg7~gsO|I! z(1%l_<7h)?zfI7|Q=`Z0nSWj7pY+&NB~ah}EFWLyZ)*XibKHO+dJ)8V&L4GG!sQOW z=zSJlLSpJfD5*y_EIULKpM>~H#U|?N~$N#j8vHkz= zVodBD4FA0jP}L3LjH>cT$9Klw{o=al)y~X59?fe4E)N>AIra!e7%Txzmj5?!HJXBe zNFtu>989@t)e9Xvj{@?qe_$S@L?6M6-;DQ5LC=oXPwTcO{7P1L>D5hBcdw7Esg5{1 zYqY6QdV3VU(i#CI;2vEqj6r(NGSuTNi-1MP=V?60In=`nY>>fX5X*zm*f?BjrZwRK zs&G`bPP6wxH}tMP!Ktvh(nPB4>XRrGYEyV-Mb6SH9ig$<5_VpXRQ!p=k&uGX7-C*7 zp4d%M?I)_|uWPJa+>?G-Ve@PBZ^W20VjNB-g1e0%~)^s3# zNBXq8ur0suXdFgMmUbkjL*cr=7-2hBQ?fU_J3u?Jl3&$_E(;i9MBO(B_)`qu?T0uW z@QGqGc^^y$-)ip8{3YXlMdB}Jf4|hc9)ZXPevD%A#!%jG46)MiOre<*&rG<|TuqS{ z{)mh6J33oapBKLX_i;^*Dj@8pmU%l(p#C9$5W?bXls*c@}+Qm<& z1Zp2?j*iVUPA|F7Pw8flzS!}L(vwHhkZ-jSo24#U`h0(^77Tl2F4n}V6oa91GMwYR zst-LhbJ=2t(Hu)dno1VC7Q}OMB&?;`H>7H%ADbMYDa(t?hkp6=W@}%(=(BrhvduT` zm;zFs1uHdz_~1SHJ$9sWE(zJpbLUIVd!>I;N%N!`wbtxf0sy0y&+1`oF|vwko~>In z)zZY27TIK()fXRXA05*hg{iKeMszMZcP(0_H~MVmD`|q8!hapj zseMeNJEz#9Zl^YM4SPo~V|{0%en#0xKL7UxzvCY}-{|Yqq&22gIJTzj7`EIb|CZ`HEHGhgdcxoC-v^`E&_iWz*$}0Ti9%( zys^~MfcQn5ja&UVQXHH^tH;>1c`ZDN+tajp=0>*dC!2PIYT&E(yEz+|YXez;?twHO zCc^#98J02(b6&78!a)c)rfagBFPea&W#d`)%@e{ICuV=cDB7)Z5-vnJCa z)G_02f7w3f*5wv^#=a)yO>(`m{ZMf>(qaGGXaAx3Y@y@z34!ycx!a&KZQ*{FL6#pZ zs}qNSb-*cL$1Th-a4pei;Xdlu%oF61`a$73eakIm&AYSDXXI)AUTEXCel5bM`k{UA zwsg(4^X$>*>Y?w>Z9tqENyRxD8V4h&aVDe$(VK`ua!H&S3_~RnXBSa&%QJ=SnFnwqG&hee) ztL8eBzuTKtk|xTprt9}zQT`Kf9q;eV))D-(-<-Z%#=28mkL?nMnSg5vgbDl+xEY`t zSQ{7~Kp$uoz>K^ZCg+#P64@vZoeVNKS$!zNPs4S5YCm!E#W93e=$Wm;ksU~FZ2UPBm z*PRT{18;~eNUimbJ76iWHLw_d0=0wdE^9rwTP~0UX%)SV@2+_r5U_^&OnVoxZXa+9 zPx9^~zBl__HF`F>oV1CwsI;fFowN)hfhvKc#NhWB6|!-3ssgU<`xpXIv!GF=W(pIZ z!OfT*GHbCcL=XP$zL*8ERpj5CCSHSXWWwJbF)zIa4`MpSp2Wn&j78(cDs$iD?&NCZ zCI@i`8Q^)^?l&n5Ie)PLSorQo<^B>qL)AyWSKcq1loETL(UsudabGu= zE`q2piV%h;cO(+>+X%!6G&$rEBnH&FV7?#BXjnfagSkS$-xN@f&|2A!=f6Mn5Toj1 z-MIgZFtQJ7Cuv}^k@|W1{mCe#CprY>TP7MBA{sIXMG0x*Ez7%V#A?(|&NjBkvU9eL zFHIP$#H&Ofxx5wc^fzupSda|yIzDI*oGDTV|5|$XTS;-gL8Pb9VS9;E zeuESc_u6=tMWs_JGx}ZtBFxXpPtDH7UWr`g?VC=O=aWSEu;2gQ2js7XJ@ej=?CVcGc3i8p>QwhwQoxOx6rSY!P~zhX1{Hy7rmYJ zvaSQkfGubV>sD=fs!4cjd;p4i?!YtbYI?Q@yA6tYBE|faTgPtVXI+>E+BO;ft@E7rouRzht0gjAUwL=w!5If@QE}=46toxv2FM zIjLpj+2bJbE%8OvV~QhzJulhK-{Y0J?%kV!HG<3T!#`Q`^ss0 zsz5kSkp_i|V+eYPY$$ffVQ6RwZ-{Rwc*u0f#!=ytYRF|s^ipGJfl?s8&_u{X)KSXO z&C&2Oayvb4k7_OTb z89t&rEA&pQ720V{AW`#?`7N~LJiJ!=T$)?TRytHVKN~Q6Ia@X>r%Iq&E#J=VqF0v1 z&jw}y3t#uodX%~qGfM+$T{I5!OVd@e6@Yx#m9uDS!b(s4*AKI>rJY4t(n9I|1#b!^ z3i^r*3wH{zix;N}Et89pECIz_g+rEGGyKy<1qw>7d?z>cUNgkfUc9ynkS$B4!uFUO z9Z0KXb^$Q)#ukERDO~)NbYl)_cJ922x!S)fxEj5BysCBfy6-!^$iad{O zikyu+j?9Z3j!cUjVZV!v#WUt8h)jxSG?k~qX zGx5&2Fzv631mcCTN1J90e;B?Rdp90AEI&FrI6A^Ow$08mTronJ#m8UAr#6-m!^c<0 z<7BqGJSxC(Hsa0dB(d8f57Bw$oa+2CT9eqj-;Q*PVnq@V@YxPvr%)hrz z0#E7~RW=w{+14AF5*cGxegm&SY%{GgZQJKOK`yy2rPmlo@JD7xPV;~YdtKpLAET%K zmIcpA&sopudq9#>5)}hG0~v!51J7$d-?6f>7IJH?`4UF+q`0{>7vMaKHb?EQ$x1Aj zu(iYdWd&GU$wVmg`pf*0_L(U#4J>rjT0v6hGjuO>VFk z47=EAmOc0}y=NP4M|`_?uV80;`~BWeM?${jJw!gh9_P*=-NnN0%R$YxTTN z`kIht8^I#M4#otifbINfeP zCwNibf|fa&PusfM&fA*WX4{V2^4f;m(%MEY@7iKLjDHohCAGsCChO2 z2uYSOeeSayssUnh^R+4J(Fz^}6rUshj<=N50kbJAnwZ~N`e>`o?Mspr$jr{5vJ zKznGr*(`{(hzy}j(sYCLw2URRCCp9rIW_BL0c>x+_^V7BOzN|OKf88UzPWwR$f%`r zF5UetVC>BVcAM(CYq!)J!}s25-y7FIcTWYxzwyPsf3NeF0vYS=46+ll+}p(;kRJ?h zL$IUiopI=cD}xtsSCx75zbbAJ1^+_E#bsvE)4dblmelh_+IC|T7sSl6Fn_GOBsDjK}qiZaGrHUKlXtHRzyqqeS{rj8o=3YDj+W; zToYSJr@nN5F)uk{mHz(w{;$01hz=Hh)i03ysh!jBnd%TV{>rPO=_OeNS=>Zs27Uc|t%LZ&iR2EQd&Pr+Lc^p}`W1j@$(7bY z>2xmpTJ3smNo{X!WNlmRG<(%?UTsV5hH3st+Q@7zl4<;i=ZIO-*lYIqJ z7#gu!u_~{(cy+op^wg)69ZdVc*jw~h;bGYE44w>TnxmB;O0?8#D!#b%8DlGH3L0Km z^$B2;0KBzp%D)))<%Sz$7t?>E2QmaQUREL2kwK@N}(m9Ep6*U0?U9Xl0 zFE9S10ndaD1>!=ZNGUw-hSp*)Z+qR5?da2+4mzevTeVgJdWIwXBhR7W%kiv(t7T1X zB%{F3WKAtuH(93*Lrmx>OqFU6OFCniXuPCWWQU}OWcZ}`WbTOF@40gp{mfv~q5{8* zsee)zn>{ZPC4ggwnSd80IJfDlgMJk_?u_SJ>or}*{sSxiB*=f~&>&cJ z1X5HHLO)(82dGV`Ug*%jgIYi|yHx%|Hd{?k2hq*Rcl!{a!10pN8tQ}V&&Gcs!{Be~ zxm#tE0raHm(7A6BHAG6vh^#dW&$8cYbo*c*1O7DmA!SoybKeb79{w^>IO_Rt<}5yO zp_ln9j~S-S&54wLVz8PF$NxMJRR^EK)l~s)rVwQ^@0+A8i{*K*tE0Qr@?fq%dH!Kk z;PWbUE9y^|t~l6hmz+FQ^;!RL{z+_9terj0U<*5@irLL;oi>Arg`;y% zB7 z1<&2rFS@q;2Vg-6#AyEtpxt54;ntD5u>5GCl%QguNTEew{NSLFpfI5*p`=;;wR(X# z4%rgR<_vs@0^-=>T;eD}uz5InsCmSB(0LdEAyCBR!V!ZLb%@)HFnkdrf0q!WQB-5s4|Vx8=)>AUjySm) z613(R|0G)xpcAG3fQ$6&8qjF|nG)jW7*pEf&JAxxG@#00(7*6Uq>Pgn)rB6|aQT%% z2YntVPpL!PWenhp_)F&TMof;8JJ%tuFpBd0P3pqVaIxzDX##Z?pmO2ClIZ3bz1j$V z=&uHyP~>aQB`PUtZQY+H^q7%cAYyQQK5rh(s)=ljc+LnTsEeE)`pbqXlB}!l&*ccH z3GzRr4Us&>cwOkPKUP6Vci9i%PpJ|U!g$n%^Tp}TmN+**@>fO+@+9@c&|-x_mi*j} z$oRp(5`j4M)ffn!ANm8(1Y_Wlr$2wfXOs?nWBHvF1&6acfLd!34ms`fCoD#bfHw-? zbCCW${BsX~+u8rM)Py4D^?QTxeH{viuqyyo>njv8>gR6g3ex)926=1i6MRr_hqbr0 zl>O0cRamAi$DoX_)E=B?O?e@>u{fRfimIwMyn=c(nVC{d{mkOX_ULH8^<14v-yo(= zMy+*8*R$Bwr9r-M0^IPpq)q{cX4H@cEB5s>BI>(te==THID~KOUFd`#0{$zgMez0S z#m2>YDJXh;97olcQLGIGI{xctOjP+F{xZC*NC?y$U6h0=L9qV;jWWCbQ5?8{LYYKZ zMK>-t&W*S7)<-8csRt4Wi(g3zP)&OLZFpl)5NbERTdg09AY6aVAx53;@%Q9aMngE< z5D_9Q34#3|U?%FW|s)zhfr8phtH&_?|S|H{|0;T1OHKAnH+McQ0sgBlXxdF z5p*_1OkRg3;>4le4|4}SyR zNn`}i4Z^Gi=m>1s5Nue4qz$Vn`9BX|gqv{i8|>m&un5%NS1sK?PDAe9-;U$YGbx8f z|MLi4qNnt2Pnb^HZMABg*2z)zdi^7KzhWRTZ+1x#Hig3CI{eS@Fqn?02nK&sM2yfP z6c)uHhYZyk_m5K0>z}|IgNdNJDI!ZK9R^G15V}oB&KDv*P8R3%?`6P1{i5~F@NiNX z5mAF|oW5rQeLBFXeK=UxwOVyYqpV#v3gFZ#S&YdgfL`tlQ>FF7g)Kr>xudxeNmT zUQnw)g*57;R-1+_)b>~}Zh()^bzI$<1lp2_3`SmO*#6fNs(Mp~jMDMB5BBpfMW@Sb zz=dLm?0EUlcG*Ng=?y)XLEnak74$*s2zNSem#$&Do1iUX#f=rHB%tJ*$k-E|9 zH=>`Mgxi@#hh>V)2i0Ed?>n-T0oP)wSxOt%l2mt^erARam=Y-GzC#`NZK~BAYR5O z|BW1SG>)r|`cz&T4p;rx$-E>Sm->=o30Nk4%kG%~$X2OP*8hpYDiQLB{F8~#u$7Lr zk&X@hOvd}qgYXaIx<3bDba@rDHqZ4r*lJ?;>#p*@#)N-C3s7zF>s(OP(C#Q*)=&np z=lFjA4*fe{;$Pg0|H`BI-#*759z_lI3Q_+tt62z}KxFEX2su9KX9((yYYO*k zRnELdi3|35nIGUy+aKe6^;>t1u5uWIR|KX0CWjtM12z{QaZaQJUi42d4<*QoRK3TU zOCFF<_a{Y>U+8lF!0N`&hM4d-Vx=T^C``;5&lQnUrlaO`2TP~20@1$Xg4 z9{qKHxx@eD2mj$8{{)mtiP55Yltqm(dy{M4#i?3Y7Rs8^1G~$7t zEq8Z9G|<+DgE!Z?l^?>()`qX(Bd8jhcsZsT+5qL10bm82XboZ8@Ym;{s^Q(ax}2aU zpal`m3I97${>Fgm+{zz-+@`ZW2UCsX4(|G2NU(rHa2kX701@OIB*p)Of@mW)`dnJd z{V!~|R};of`k(24vGU(BVvV3EBM5!uAD@WWBnZO{@*AO8zx-34AvOJNCx74W|99N> z$6w?RFFe&6Ivr{kvr7*qMGndd=`%C*D3xC`9Bc9`q!-fs-$7X2{J*SGh1sP6(*3<%-#*2=h}0N&x9I4fHYPKf%vJh!(K_Mcu#M;9sB=%$+n83DP$00PZ{-$^fH_0mfYdsv2<}8~X1speN7|$N#@y=XJx9znY@p*XY+n z?c#&sm4ezsTqlIipzw2o`=22x0kjE)pAB406jUvS2sg~2B-A3}zk&ZpC;gvJ1w9-} z6hnj-22lbk7m@TmbP&0pGTeU)X~m&}5p&R?m&yDD;J${eZ=gaK)nt+*vNCnmHxKk` zrd^2!p#%i4lOCgMpwFRmp`(WCgz|@ahQfzRBBI57e*0Gp4@ZD*Bl5jF1?8-!1T%uZ z#@)X!p7HQU9`mc&bir{kQo(&SM)6`)yy^k4FbHs{h=gVT2;yf5<(*i^x;YVMTsdb@ z;RMi+MZWjc6BV7X+J;yPKt4+m97EN@4x*9@_#MB7WXjln|LCC>66gSzIOND2LjCp7Z~Z=vIEputE5wv#(JaA}T4b-@1qp zQAshZJL)>0-yT%fe-Z%X937}Rm=YWjFjQF&g^POuDrj~imVbhxM2_fCHKb)Wm)Yf2 zBIUFTDXRqX&*l)j9vL{w*HCr=i$@)47)STSf8qJvCz-62H2; z?esp}WyX$mGuv}I0`Fn??Ak>YK(BaYM({{zSx-iN#N?Xk&A9%ro%KeKKJ+ z3rS7)VT?o9bZxe(D(N{o%Ps@(Y4)Z;e&53O;CMgl=hVuSa9w_DXJvb1VV&t)4=>3j z6g6G`RSHi&#fcMi@PwrER-%a<%2r0FgfqV?EO__QPj|pnN!ik938VY=zEW@td;ivf%k# zPw)?1UE_&Z*Mjl^3?GSqL#loJsrF}}Ne#l#7qqxOV#)|1X&kQ@#{Y*3JndtS`MDG@ z^$+-N(XZ&Pq4c3vq4QCYJ z!p1TFSkfQD0xe6GPunNdFx)kT;K~We;uK_lMatmptY-W;)#_xw&h=KFhlIRZ-ty=q z+wvsUf@pP~Ew|FiTi4!8w;EjIW_7e(mGlv-dP#?8)P~&_tK$0VCNV9!MaK-&`f2{6 zUbE!WQjqG=>_;8N{r&XmMfUhIeId#WXLsfX*PF@v82;Pa2IpG^o1+t|;u(Q^nrrzJ z9)@{t_D6?x z(WJm7fx_bCXiQ1tcap}DZk)`IcVUUo_hHzbK9_3|@3xMdXvBQSgD#pw5<29eIEEfg ztMJXZW3S~~Cfct6!-JWw_eZANS_;u&+f9jt%#QD3wmcmL#cf7uE>#>S4e@owQ16i~ zj)pGa`0U6BR2{Ek^OFf1P{1~>{7SulRX#G+ySX6G}Y8DQAX_3{6^t(jW@>i2zgdra@%$fB1DVXl5#wz znmD0xWa9H7zi!ViHNnCBO^ww(`B6{&Y9dT=sU~ILD^+<{A$6J|$_q%adZvb)CEUjjpHA%t!*M|{sb975uq=|%zbm>e$R z#huICi5W8&`=kTTj`9?H1fdzCHdk0rY?sIK5iO-ZV2y9b(K%t29uiJ3|1LFLg8Mqfp!F*jd^<6Q?|d$%k5iaiPXjIx^bb`5T-kmws*wygd>ap5t%opd?V zck|BBtq<4!(vU*28}9L?LyHtAT;fZO7I{**>6d0LGR<)ASZuy2X3emJ9tS$}4k>UX4o=k@+S0C(})+S}#GbL5p0)4H$t$kj-&=&>{9q!rg zolPQow9J?!=(rJR;c~qpy@i|X7e)@vO`>{qRhT3gfC%ee@Fu@Q`&~)XCvSOgJ#SIx zFoHgXO|uJ`3%UzShlsn#yNbJvySBT4ySye1Zy9fGZwYS=Zv}6CZ!vE*Z#i#WZz*qp zx01KvqsXK3qx7TJqxhrxGPMu253>)M51kK{9j;rbKwovAeXssz4U$+Bs55qekdt}aOZI_ViRG42bxQYcNI+Gh5qrGv5{MHco8 zW=OBo=Gvym6cbwGZ;5$O~!dbi!l56!Ov;$i`q6 zQqpP5#;O)_(&-P!uv3*MP?^f{sa7S>?8v=Q%~hwwmZMTFRi{pr!&WUciPs8?KUPgt zXPT2nE!Aw1ZqaHHZ&7cNZ_#TJEsH-agfCUur22$Ujgl-W4Uh%MP!yIIs!UrP;2-E% zMsjLe#bv10IcIVzVp7S(QAwy$DNIv|S;h9tRZhc|Dx}eZ<>Cua4?HbvXX#vIR#ZWp z5-pz&6YmRrEXz0*(wN6$%w+2d2nrXc6{g2tAC{k(P&X<(QgrJQEQQF(QT2! zk2y`;mAjR>l|wEFo+dwlwye3zsTcQ@)}d#LCr(O|V<21lLRIFjU6R%YkGG z3I+-W3TY^l>s26>wn#Y0K?p= ziF}L9fT20ZsN)#xorvv-9l33}ossR49focGW&^tz0#gH=ZKKPt9zouP-id;$9XiBR zprq>9>coLT;~nZnI-Ze*p)C`YBol2-6ODNjeeP`>kG5rcrI@AdFvnIwnbVl+WSWso z$K++E+d;K$f^CClrPJi%;hF7&%Xc0{f^r=ySxjq`Ym5`Id&7-`zqWOEmbRC61hxfs zTDMzwytbi#8+dehXM1?mBC{g(Mn_uJAV;xY2E;xXf~?J?jnuT8^8#z)&n!bihL z!AIXm%ty^f&PUfr$_L=1`UfL=SyXu>^3N{Q@vxq zt$*2g>2_)70eWn21FX`#kiO8KCHuyq4I=D_T~1uGTpIljeJuA@|498p{lZL={1T%y zNVB7MnSE*Lq5P2|JMkqhWZUU-?b2hhk~JK(S$;?NEbE6^0!N2KrG=y-n#f9}7p6>} zNK2&?rt&3`m&!m!88eZRN?S%nHIb7_e@K}fyF9MYgn>`CDz12&;f-vrYQcL3D%n!i zq67wP*}^YsTES|^vWcpdv$Uv%n$6P9TFv6k>do@add;GxYKMvNg(@4^pYV#_0VHVw z^Z+`F#PURyVT&F79Uaq1c1=sw4B0xzOm;;KY?)YW2^DOGDQq!Im41fGVYott)RKCJ z_yp7)Pt)4zQfImqSrEHK^QQxi`vf1;GIoX3s!?S#`nm*y#KmES;jv*t(<;XZcBN*G zW`$<`X0c|qX1QkFW+^=7Q;l7QTe@2Yd1@*QZ?n#-J8aSv(jGDbCG%_Ihfgv4R` z9Sl=&t)zB&h1xs=h@K!}AYmYp=6!Ol%3^_yW|n%EYL;dL?F8)v{RG_v0}Cw+y>4Q1 zLUJM?0g$+mu#m`;z?0aR(3t3!;FfrsaGQvhfR+eK03|9VC?(nsn-A{|;|?be1BP8q zLu%E2>-?5nEc7n-Et;zQo@u#!4mdHF8x) zQR|sQU6k2d7NJ zszxU-sm#=>StnPsj5|?-Z>~zSbj~X3P}zDeVm4w}^VSqhr zbokXJ$g|Khkzci4ho~@Gvs$HEW1z%%j(VOoT#ESR+Ep?uR|{4v##Q#p z8cTl7>dr0AF3kzd3e2_6w$6FYLSGxWba-ZacD9JNTeZ_soecOG& zeO`+OPzI#UC#@&(C-s#gpCX?spIo0( zpF%r;TZzD2^_=~z{$b;x+o7Ec=)S!Luu}Y-^IUQY@Kr@CL6{ReoH%4TG`bGGFZWaz zDtaz@t|A7!C@YoF%&8q_A6mL73*~2Nyr_oEIvuVZddyX_rGa+Ke_KB5_~DeivBY80 zLY@)@voh&LOp=3XnRFtizJPg|4CE#;!IVtea#N~cPA2`4Np`OCq(W0`KAozh;vMTZ zuRmu2wl$Sbsb*24HMUNn*^E}y%&|_QX62j(YNckYbgNdYc&mD=e5+ooX!*<`7`{?v zi|Z3X5z2z31;7emNdYbgt3WJH@K1DXBe^xLr!#cwUb7)8VsXjDb4jRiDa>$*Sx@y_ zS3=+_71B$<*75bIC!V&o^QA79D>@)$6e1mH!80%QzA zXj|nP!L8J)(W=m@-zwIs)+*Pk+bTscc{;aieQSAZja(lLAwPk(t+~l*5ciVSEn}J? zo=>u7s858@pJ3R68zgnhD`)1dK~@Cy1N8%78qVYfm8AmP`K;Nj>8$w%iwTPfs|m{q zYZeO@D_wAMeKHtO4*)OJFMxUKdBBbJjbOKWH}Gx!Ef}pH4GgLWftBi&z_t)`$Q}e2 zk_-VrTx~-d)E;ymB$o<-<-p>T`5TKhYcDVmf(8LWd`@Ui{9Kg<3Z5#S@`&c6Ejq2F zz{U`J$Qi`p1nnfqRaKzysWfvQ9?SvJK4Gzy7AStI%v@OJ&wtqOXvsdUM%efFjIo;v zyhayNN1N%nMif#7P3K>K5YhzAY+b_%sVGgyU%wa9P@0*!ekY{Xc&P2!kd?o8=;7I6 zkb`?D;aOvlmwagI*=&#tIONWp<6Ef$9L#w}olaU`M_ff*%U#J`k6evhGhFev8`w`0 zxESDG8Qp&c2Kf~FBz{!w)FCMZz2?xVo*URVzNTI&UrYCa+fB?yFr9Tp6@0oh=j}&RiYbzXKM1lT5;5 zMZQ(OxxS^oh4u?>`vTY1*Y;QX_l@^%_jW+gb9)D1t@tJ9rQ~eEcN%RU;aco|;-2N+ z=qdEM+(%uw=%whTie%wsQfZ&&TJ1jj-V&%RoS!}SG97Z|bia1*v0}^m4YXl>hxaV$ zhhYJShePobkxev;m0~%Rl{|`;0usvhC5o3~RhktuijrbcnoTu|lVW9%l^vx#*3^W6 zPqHf3e4F5nWUh+IdjcxSQWdiV0&K}bBMz-Vj$_G072DYlsQL3vgH1o1dYfjOMw^zK zew1(=M#1M#t)p~*Fnh-%`2m0rz@vyNk5cKk*uvk^F^*)Lw_wkZtaHd@8%IYOib3g9 zMj4w#>9JtzC#dX)%O6Xzs3(YzMBVZ<3SO)E`3O*2g+O-oG!A6QShb_s6rZV8YhgZs(1pp9!T za%y_r2eqsiIf%KF2pA$0`{}nZjKMYiTGkaD^8_G#g2;i$fhd}H$u(0yO>DTcIJ4NZ zxEnr9e3-zWz?&do`M`p&8M!7}0Mcqc;MxjNbMS&tg zQA&|YQMUc&{d@hm{mK1+eplm=nwdMuUH?y0Z)&6c0T zB(KS%&EpqB?&uGl_)-G^G=1Vv&zW+?JCiGc6B%=x!X!HEj9&-&o8WYM*Q3mt!?L;6 z1wXKT_x#TLx#YFO?{NQou_tw4`BCNhgS+?loe2NaT%5~LfDk7-tG(6^l*d`JzemsT zP~inkGoKGFrWMpzgu3=njHdI^9K**P!<;4Hd};Fvf*!%jX=k|1MSN*9!pi9rbMlf< z@10tdp1_uK%L+oo5Lj3r)Vv}*W9{3*t#X3Y_<&|!xAepS+%9=&TY3`MdVTr#c?|fi zLzGxhA>!=dq%*T@ryBsXEZ;Q4w>B1ZY~#xD+)Hmv=9Vh*W!F$=T`})XtS2k<_-